caching patch by Michael Grigoriev
authorMiklos Szeredi <miklos@szeredi.hu>
Mon, 8 Sep 2003 11:14:11 +0000 (11:14 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Mon, 8 Sep 2003 11:14:11 +0000 (11:14 +0000)
ChangeLog
Filesystems [new file with mode: 0644]
include/linux/fuse.h
kernel/dev.c
kernel/file.c
util/fusermount.c

index 792395d118c130858057e56626454b421cc4a8d3..a55b11edf84194d11950fb13c990196a231417f5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2003-09-08  Miklos Szeredi <mszeredi@inf.bme.hu>
+
+       * Integrated caching patch by Michael Grigoriev
+
+2003-09-08  Miklos Szeredi <mszeredi@inf.bme.hu>
+
+       * Added "Filesystems" file with descriptions of projects using
+       FUSE
+
 2003-06-02  Miklos Szeredi <mszeredi@inf.bme.hu>
 
        * And another spec-file fix by Achim Settelmeier
diff --git a/Filesystems b/Filesystems
new file mode 100644 (file)
index 0000000..3d51d3b
--- /dev/null
@@ -0,0 +1,25 @@
+Name: OW
+
+Author: Paul H. Alfille <palfille at partners org>
+
+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) <mag at
+luminal org>
+
+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.
+
+==============================================================================
index eef77d9faa615f754966e8dac601fee9aba5b941..507d8729c009a6028134c16908ea31a5c131a2a9 100644 (file)
@@ -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;
index e703b11ebf11dcaa0e1991fc66a028dd48cfb325..cdc4b6c1490570bd37b5af1a1597cfc377ea1a24 100644 (file)
@@ -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
index f4688f7ebc993fad55ae6a71d324e9c209f50c70..68bf66081e1081e19d0a80d9fb37ea4d81b2a315 100644 (file)
@@ -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;
index b76c819148354aa672c59fefc17ed7e3e60c6430..754b6a9613f5d2795e6290ffb3dd82a18fa6a967 100644 (file)
@@ -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;