cache ENOSYS on some optional functions
authorMiklos Szeredi <miklos@szeredi.hu>
Thu, 3 Jun 2004 14:45:04 +0000 (14:45 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Thu, 3 Jun 2004 14:45:04 +0000 (14:45 +0000)
ChangeLog
include/fuse.h
kernel/dev.c
kernel/dir.c
kernel/file.c
kernel/fuse_i.h
lib/fuse.c

index 3d32987a4abac05fb9eaa1148da41040aaf08ba4..da590deb93451a7bbd7b7cf617a8b83cf57f6054 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -10,6 +10,9 @@
        background if mount is successful.  '-f' and '-d' options disable
        backgrounding.  This fixes the "Why does my FUSE daemon hang?"
        newbie complaint.
+
+       * Cache ENOSYS (function not implemented) errors on *xattr, flush
+       and fsync
        
 2004-05-18  Miklos Szeredi <mszeredi@inf.bme.hu>
 
index e3e433347ad5922d5c472c0212bcca91327b76ad..d298cb3cb8347a08ea6d4b1754b51681b8955837 100644 (file)
@@ -103,7 +103,7 @@ typedef int (*fuse_dirfil_t) (fuse_dirh_t h, const char *name, int type);
  *  then set the callback pointer to NULL.
  * 
  *  - fsync() has a boolean 'datasync' parameter which if TRUE then do
- *  an fdatasync() operation.  
+ *  an fdatasync() operation.  Implementing this call is optional.
  */
 struct fuse_operations {
     int (*getattr)     (const char *, struct stat *);
index afc9f4c97b2ae1169902fb6ef1b9f0d63e589c33..af20de8d7134c9f0a31a92b675a65fce16224a9e 100644 (file)
@@ -543,6 +543,7 @@ static struct fuse_conn *new_conn(void)
 
        fc = kmalloc(sizeof(*fc), GFP_KERNEL);
        if (fc != NULL) {
+               memset(fc, 0, sizeof(*fc));
                fc->sb = NULL;
                fc->file = NULL;
                fc->flags = 0;
index 110a4720727db3b41c48bbf738da7ed155fb930b..e941e3e418c5911a2f57a5d345588f20c2c1cc09 100644 (file)
@@ -783,6 +783,9 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
        if (size > FUSE_XATTR_SIZE_MAX)
                return -E2BIG;
 
+       if (fc->no_setxattr)
+               return -EOPNOTSUPP;
+
        memset(&inarg, 0, sizeof(inarg));
        inarg.size = size;
        inarg.flags = flags;
@@ -797,6 +800,10 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
        in.args[2].size = size;
        in.args[2].value = value;
        request_send(fc, &in, &out);
+       if (out.h.error == -ENOSYS) {
+               fc->no_setxattr = 1;
+               return -EOPNOTSUPP;
+       }
        return out.h.error;
 }
 
@@ -810,6 +817,9 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
        struct fuse_getxattr_in inarg;
        struct fuse_getxattr_out outarg;
 
+       if (fc->no_getxattr)
+               return -EOPNOTSUPP;
+
        memset(&inarg, 0, sizeof(inarg));
        inarg.size = size;
        
@@ -833,8 +843,13 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
        request_send(fc, &in, &out);
        if (!out.h.error)
                return size ? out.args[0].size : outarg.size;
-       else
+       else {
+               if (out.h.error == -ENOSYS) {
+                       fc->no_getxattr = 1;
+                       return -EOPNOTSUPP;
+               }
                return out.h.error;
+       }
 }
 
 static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
@@ -846,6 +861,9 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
        struct fuse_getxattr_in inarg;
        struct fuse_getxattr_out outarg;
 
+       if (fc->no_listxattr)
+               return -EOPNOTSUPP;
+
        memset(&inarg, 0, sizeof(inarg));
        inarg.size = size;
        
@@ -867,8 +885,13 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
        request_send(fc, &in, &out);
        if (!out.h.error)
                return size ? out.args[0].size : outarg.size;
-       else
+       else {
+               if (out.h.error == -ENOSYS) {
+                       fc->no_listxattr = 1;
+                       return -EOPNOTSUPP;
+               }
                return out.h.error;
+       }
 }
 
 static int fuse_removexattr(struct dentry *entry, const char *name)
@@ -878,12 +901,19 @@ static int fuse_removexattr(struct dentry *entry, const char *name)
        struct fuse_in in = FUSE_IN_INIT;
        struct fuse_out out = FUSE_OUT_INIT;
        
+       if (fc->no_removexattr)
+               return -EOPNOTSUPP;
+
        in.h.opcode = FUSE_REMOVEXATTR;
        in.h.ino = inode->i_ino;
        in.numargs = 1;
        in.args[0].size = strlen(name) + 1;
        in.args[0].value = name;
        request_send(fc, &in, &out);
+       if (out.h.error == -ENOSYS) {
+               fc->no_removexattr = 1;
+               return -EOPNOTSUPP;
+       }
        return out.h.error;
        
 }
index c9a44fda2684d3af88a0e57cd3a63d9d07df54f2..2067bd7469f02a6df214b7abcffa67d461e1c4f0 100644 (file)
@@ -99,11 +99,16 @@ static int fuse_flush(struct file *file)
        struct fuse_in in = FUSE_IN_INIT;
        struct fuse_out out = FUSE_OUT_INIT;
        
+       if (fc->no_flush)
+               return 0;
+
        in.h.opcode = FUSE_FLUSH;
        in.h.ino = inode->i_ino;
        request_send(fc, &in, &out);
-       if (out.h.error == -ENOSYS)
+       if (out.h.error == -ENOSYS) {
+               fc->no_flush = 1;
                return 0;
+       }
        else
                return out.h.error;
 }
@@ -116,6 +121,9 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
        struct fuse_out out = FUSE_OUT_INIT;
        struct fuse_fsync_in inarg;
        
+       if (fc->no_fsync)
+               return 0;
+
        memset(&inarg, 0, sizeof(inarg));
        inarg.datasync = datasync;
 
@@ -125,6 +133,11 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
        in.args[0].size = sizeof(inarg);
        in.args[0].value = &inarg;
        request_send(fc, &in, &out);
+
+       if (out.h.error == -ENOSYS) {
+               fc->no_fsync = 1;
+               return 0;
+       }
        return out.h.error;
 
        /* FIXME: need to ensure, that all write requests issued
index 12991396c510e80252d70871178344e483874cab..d5943a9d9d5e9bf23840fcc34b1f3c400afd9a9e 100644 (file)
@@ -96,6 +96,24 @@ struct fuse_conn {
        
        /** The next unique request id */
        int reqctr;
+       
+       /** Is fsync not implemented by fs? */
+       unsigned int no_fsync : 1;
+
+       /** Is flush not implemented by fs? */
+       unsigned int no_flush : 1;
+
+       /** Is setxattr not implemented by fs? */
+       unsigned int no_setxattr : 1;
+
+       /** Is getxattr not implemented by fs? */
+       unsigned int no_getxattr : 1;
+
+       /** Is listxattr not implemented by fs? */
+       unsigned int no_listxattr : 1;
+
+       /** Is removexattr not implemented by fs? */
+       unsigned int no_removexattr : 1;
 };
 
 /** One input argument of a request */
index 255a24b3293dc23c38f9da1561ae33fbe120eb51..05d9713ad353f995fc78b87818763d6e6e045311 100644 (file)
@@ -980,8 +980,7 @@ static void do_fsync(struct fuse *f, struct fuse_in_header *in,
     res = -ENOENT;
     path = get_path(f, in->ino);
     if(path != NULL) {
-        /* fsync is not mandatory, so don't return ENOSYS */
-        res = 0;
+        res = -ENOSYS;
         if(f->op.fsync)
             res = f->op.fsync(path, inarg->datasync);
         free(path);
@@ -1000,7 +999,7 @@ static void do_setxattr(struct fuse *f, struct fuse_in_header *in,
     res = -ENOENT;
     path = get_path(f, in->ino);
     if (path != NULL) {
-        res = -EOPNOTSUPP; /* or is it ENOTSUPP ??? */
+        res = -ENOSYS;
         if (f->op.setxattr)
             res = f->op.setxattr(path, name, value, arg->size, arg->flags);
         free(path);
@@ -1017,7 +1016,7 @@ static int common_getxattr(struct fuse *f, struct fuse_in_header *in,
     res = -ENOENT;
     path = get_path(f, in->ino);
     if (path != NULL) {
-        res = -EOPNOTSUPP; /* or is it ENOTSUPP ??? */
+        res = -ENOSYS;
         if (f->op.getxattr)
             res = f->op.getxattr(path, name, value, size);
         free(path);
@@ -1081,7 +1080,7 @@ static int common_listxattr(struct fuse *f, struct fuse_in_header *in,
     res = -ENOENT;
     path = get_path(f, in->ino);
     if (path != NULL) {
-        res = -EOPNOTSUPP; /* or is it ENOTSUPP ??? */
+        res = -ENOSYS;
         if (f->op.listxattr)
             res = f->op.listxattr(path, list, size);
         free(path);
@@ -1142,7 +1141,7 @@ static void do_removexattr(struct fuse *f, struct fuse_in_header *in,
     res = -ENOENT;
     path = get_path(f, in->ino);
     if (path != NULL) {
-        res = -EOPNOTSUPP; /* or is it ENOTSUPP ??? */
+        res = -ENOSYS;
         if (f->op.removexattr)
             res = f->op.removexattr(path, name);
         free(path);