From: Miklos Szeredi Date: Mon, 8 Sep 2003 11:14:11 +0000 (+0000) Subject: caching patch by Michael Grigoriev X-Git-Tag: debian_version_1_0-1~3 X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=da4e486a8ec9ad172eb7834a973a14004170ec14;p=qemu-gpiodev%2Flibfuse.git caching patch by Michael Grigoriev --- diff --git a/ChangeLog b/ChangeLog index 792395d..a55b11e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2003-09-08 Miklos Szeredi + + * Integrated caching patch by Michael Grigoriev + +2003-09-08 Miklos Szeredi + + * Added "Filesystems" file with descriptions of projects using + FUSE + 2003-06-02 Miklos Szeredi * And another spec-file fix by Achim Settelmeier diff --git a/Filesystems b/Filesystems new file mode 100644 index 0000000..3d51d3b --- /dev/null +++ b/Filesystems @@ -0,0 +1,25 @@ +Name: OW + +Author: Paul H. Alfille + +Homepage: http://home.earthlink.net/~palfille/ow.html + +Description: + + OWFS is a method under linux to allow 1-wire devices to appear like + files in a directory. + +============================================================================== +Name: FunFS + +Author: Michael Grigoriev (Net Integration Technologies) + +Homepage: http://open.nit.ca/wiki/?page=FunFS + +Description: + + FunFS is an advanced network file system with a simple goal: to be + better than NFS. + +============================================================================== diff --git a/include/linux/fuse.h b/include/linux/fuse.h index eef77d9..507d872 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -46,6 +46,10 @@ permission checking is done in the kernel */ doing the mount will be allowed to access the filesystem */ #define FUSE_ALLOW_OTHER (1 << 1) +/** If the FUSE_KERNEL_CACHE flag is given, then files will be cached + until the INVALIDATE operation is invoked */ +#define FUSE_KERNEL_CACHE (1 << 2) + struct fuse_attr { unsigned int mode; unsigned int nlink; @@ -77,7 +81,7 @@ struct fuse_kstatfs { enum fuse_opcode { FUSE_LOOKUP = 1, - FUSE_FORGET = 2, + FUSE_FORGET = 2, /* no reply */ FUSE_GETATTR = 3, FUSE_SETATTR = 4, FUSE_READLINK = 5, @@ -93,7 +97,8 @@ enum fuse_opcode { FUSE_READ = 15, FUSE_WRITE = 16, FUSE_STATFS = 17, - FUSE_RELEASE = 18 + FUSE_RELEASE = 18, /* no reply */ + FUSE_INVALIDATE = 19 /* user initiated */ }; /* Conservative buffer size for the client */ @@ -179,6 +184,12 @@ struct fuse_out_header { int error; }; +struct fuse_user_header { + int unique; /* zero */ + enum fuse_opcode opcode; + unsigned long ino; +}; + struct fuse_dirent { unsigned long ino; unsigned short namelen; diff --git a/kernel/dev.c b/kernel/dev.c index e703b11..cdc4b6c 100644 --- a/kernel/dev.c +++ b/kernel/dev.c @@ -359,14 +359,46 @@ static inline int copy_out_header(struct fuse_out_header *oh, const char *buf, if(copy_from_user(oh, buf, sizeof(struct fuse_out_header))) return -EFAULT; - if (oh->error <= -512 || oh->error > 0) { - printk("fuse_dev_write: bad error value\n"); - return -EIO; - } + return 0; +} + +static int fuse_invalidate(struct fuse_conn *fc, struct fuse_user_header *uh) +{ + struct inode *inode = iget(fc->sb, uh->ino); + if (!inode) + return -ENOENT; + invalidate_inode_pages(inode); + iput(inode); return 0; } +static int fuse_user_request(struct fuse_conn *fc, const char *buf, + size_t nbytes) +{ + struct fuse_user_header uh; + int err; + + if (nbytes < sizeof(struct fuse_user_header)) { + printk("fuse_dev_write: write is short\n"); + return -EIO; + } + + if(copy_from_user(&uh, buf, sizeof(struct fuse_out_header))) + return -EFAULT; + + switch(uh.opcode) { + case FUSE_INVALIDATE: + err = fuse_invalidate(fc, &uh); + break; + + default: + err = -ENOSYS; + } + return err; +} + + static ssize_t fuse_dev_write(struct file *file, const char *buf, size_t nbytes, loff_t *off) { @@ -381,7 +413,17 @@ static ssize_t fuse_dev_write(struct file *file, const char *buf, err = copy_out_header(&oh, buf, nbytes); if(err) return err; - + + if (!oh.unique) { + err = fuse_user_request(fc, buf, nbytes); + goto out; + } + + if (oh.error <= -512 || oh.error > 0) { + printk("fuse_dev_write: bad error value\n"); + return -EIO; + } + spin_lock(&fuse_lock); req = request_find(fc, oh.unique); if(req != NULL) { @@ -408,6 +450,7 @@ static ssize_t fuse_dev_write(struct file *file, const char *buf, wake_up(&req->waitq); spin_unlock(&fuse_lock); + out: if(!err) return nbytes; else diff --git a/kernel/file.c b/kernel/file.c index f4688f7..68bf660 100644 --- a/kernel/file.c +++ b/kernel/file.c @@ -34,7 +34,7 @@ static int fuse_open(struct inode *inode, struct file *file) in.args[0].size = sizeof(inarg); in.args[0].value = &inarg; request_send(fc, &in, &out); - if(!out.h.error) + if(!out.h.error && !(fc->flags & FUSE_KERNEL_CACHE)) invalidate_inode_pages(inode); return out.h.error; diff --git a/util/fusermount.c b/util/fusermount.c index b76c819..754b6a9 100644 --- a/util/fusermount.c +++ b/util/fusermount.c @@ -451,6 +451,7 @@ static void usage() " -h print help\n" " -u unmount\n" " -p check default permissions on files\n" + " -c cache in kernel space if possible\n" " -x allow other users to access the files (only for root)\n", progname); exit(1); @@ -479,6 +480,10 @@ int main(int argc, char *argv[]) break; switch(argv[a][1]) { + case 'c': + flags |= FUSE_KERNEL_CACHE; + break; + case 'h': usage(); break;