fix
authorMiklos Szeredi <miklos@szeredi.hu>
Tue, 4 Jan 2005 19:24:31 +0000 (19:24 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Tue, 4 Jan 2005 19:24:31 +0000 (19:24 +0000)
ChangeLog
kernel/cleanup.sh
kernel/configure.ac
kernel/dev.c
kernel/fuse_i.h
kernel/fuse_kernel.h
kernel/inode.c
lib/fuse.c
lib/fuse_i.h
util/fusermount.c

index 0395c389a25c5ca422d42f23a2ad6e743c37d98f..6019730dfd1be362b4273e27f9fa67eaaa930296 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,10 @@
        inode(s) and file, so that FORGET and RELEASE are not sent until
        userspace finishes the request.
 
+       * remove /{sys,proc}/fs/fuse/version, and instead add an INIT
+       request with the same information, which is more flexible,
+       simpler, works on embedded systems.
+
 2004-12-16  Miklos Szeredi <miklos@szeredi.hu>
 
        * KERNEL ABI: update interface to make it independent of type
index 9d7b92b25e84c17c595eed30d415b4142579ea9f..7c2f309888a95ac9315dbb24e465168361a5cf24 100755 (executable)
@@ -16,6 +16,6 @@ mkdir -p $destdir/include/linux
 
 
 for f in dev.c dir.c file.c inode.c util.c fuse_i.h; do
-    unifdef -DKERNEL_2_6 -DKERNEL_2_6_6_PLUS -DKERNEL_2_6_10_PLUS -DHAVE_KERNEL_XATTR -DFS_SAFE -DMAX_LFS_FILESIZE -DFUSE_MAINLINE -DBUG_ON -DHAVE_FS_SUBSYS -D__user -DMODULE_LICENSE $f > $destdir/fs/fuse/$f
+    unifdef -DKERNEL_2_6 -DKERNEL_2_6_6_PLUS -DKERNEL_2_6_10_PLUS -DHAVE_KERNEL_XATTR -DFS_SAFE -DMAX_LFS_FILESIZE -DFUSE_MAINLINE -DBUG_ON -D__user -DMODULE_LICENSE $f > $destdir/fs/fuse/$f
 done
 cp fuse_kernel.h $destdir/include/linux/fuse.h
index e6bf6694bd0801c63a9edd1d8f8ec99ff25d5993..20a54fcc6b0847067da4a2b627e546ce34587c12 100644 (file)
@@ -49,14 +49,6 @@ if echo "$kernsrcver" | grep -q "^2.4"; then
        CFLAGS="$old_cflags"
 fi
 
-AC_MSG_CHECKING([whether fs_subsys is declared])
-if grep -q fs_subsys $kernelsrc/include/linux/fs.h; then
-       AC_DEFINE(HAVE_FS_SUBSYS, 1, [Kernel defines fs_subsys])
-       AC_MSG_RESULT([yes])
-else
-       AC_MSG_RESULT([no])
-fi
-
 AC_MSG_CHECKING([if kernel has extended attribute support])
 if test -f $kernelsrc/include/linux/xattr.h; then
        AC_DEFINE(HAVE_KERNEL_XATTR, 1, [Kernel has xattr support])
index bfd2bd767dab5c5bcfea1f4dbb520ff2f15a439a..a2a44e48820c70a07823c7f0e40b9e3bea3fbeed 100644 (file)
 #include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/uio.h>
-#ifdef KERNEL_2_6
-#include <linux/kobject.h>
-#else
-#include <linux/proc_fs.h>
-#endif
 #include <linux/miscdevice.h>
 #include <linux/pagemap.h>
 #include <linux/file.h>
@@ -128,7 +123,7 @@ struct fuse_req *fuse_get_request(struct fuse_conn *fc)
 {
        if (down_interruptible(&fc->outstanding_sem))
                return NULL;
-       return  do_get_request(fc);
+       return do_get_request(fc);
 }
 
 struct fuse_req *fuse_get_request_nonint(struct fuse_conn *fc)
@@ -180,6 +175,13 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
                        fput(req->file);
        }
        wake_up(&req->waitq);
+       if (req->in.h.opcode == FUSE_INIT) {
+               int i;
+               /* up() one less than FUSE_MAX_OUTSTANDING, because
+                  fuse_putback_request() will also do an up() */
+               for (i = 1; i < FUSE_MAX_OUTSTANDING; i++)
+                       up(&fc->outstanding_sem);
+       }
        if (putback)
                fuse_putback_request(fc, req);
 }
@@ -332,6 +334,24 @@ void request_send_background(struct fuse_conn *fc, struct fuse_req *req)
        request_send_nowait(fc, req);
 }
 
+void fuse_send_init(struct fuse_conn *fc)
+{
+       /* This is called from fuse_read_super() so there's guaranteed
+          to be a request available */
+       struct fuse_req *req = do_get_request(fc);
+       struct fuse_init_in_out *arg = &req->misc.init_in_out;
+       arg->major = FUSE_KERNEL_VERSION;
+       arg->minor = FUSE_KERNEL_MINOR_VERSION;
+       req->in.h.opcode = FUSE_INIT;
+       req->in.numargs = 1;
+       req->in.args[0].size = sizeof(*arg);
+       req->in.args[0].value = arg;
+       req->out.numargs = 1;
+       req->out.args[0].size = sizeof(*arg);
+       req->out.args[0].value = arg;
+       request_send_background(fc, req);
+}
+
 static inline int lock_request(struct fuse_req *req)
 {
        int err = 0;
@@ -798,85 +818,6 @@ struct file_operations fuse_dev_operations = {
        .release        = fuse_dev_release,
 };
 
-#ifdef KERNEL_2_6
-#ifndef HAVE_FS_SUBSYS
-static decl_subsys(fs, NULL, NULL);
-#endif
-static decl_subsys(fuse, NULL, NULL);
-
-static ssize_t version_show(struct subsystem *subsys, char *buf)
-{
-       return sprintf(buf, "%i.%i\n", FUSE_KERNEL_VERSION,
-                      FUSE_KERNEL_MINOR_VERSION);
-}
-static struct subsys_attribute fuse_attr_version = __ATTR_RO(version);
-
-static int __init fuse_version_init(void)
-{
-       int err;
-
-#ifndef HAVE_FS_SUBSYS
-       subsystem_register(&fs_subsys);
-#endif
-       kset_set_kset_s(&fuse_subsys, fs_subsys);
-       err = subsystem_register(&fuse_subsys);
-       if (err)
-               return err;
-       err = subsys_create_file(&fuse_subsys, &fuse_attr_version);
-       if (err) {
-               subsystem_unregister(&fuse_subsys);
-#ifndef HAVE_FS_SUBSYS
-               subsystem_unregister(&fs_subsys);
-#endif
-               return err;
-       }
-       return 0;
-}
-
-static void fuse_version_clean(void)
-{
-       subsys_remove_file(&fuse_subsys, &fuse_attr_version);
-       subsystem_unregister(&fuse_subsys);
-#ifndef HAVE_FS_SUBSYS
-       subsystem_unregister(&fs_subsys);
-#endif
-}
-#else
-static struct proc_dir_entry *proc_fs_fuse;
-
-static int read_version(char *page, char **start, off_t off, int count,
-                       int *eof, void *data)
-{
-       char *s = page;
-       s += sprintf(s, "%i.%i\n", FUSE_KERNEL_VERSION,
-                    FUSE_KERNEL_MINOR_VERSION);
-       return s - page;
-}
-
-static int fuse_version_init(void)
-{
-       proc_fs_fuse = proc_mkdir("fuse", proc_root_fs);
-       if (proc_fs_fuse) {
-               struct proc_dir_entry *de;
-
-               de = create_proc_entry("version", S_IFREG | 0444, proc_fs_fuse);
-               if (de) {
-                       de->owner = THIS_MODULE;
-                       de->read_proc = read_version;
-               }
-       }
-       return 0;
-}
-
-static void fuse_version_clean(void)
-{
-       if (proc_fs_fuse) {
-               remove_proc_entry("version", proc_fs_fuse);
-               remove_proc_entry("fuse", proc_root_fs);
-       }
-}
-#endif
-
 static struct miscdevice fuse_miscdevice = {
        .minor = FUSE_MINOR,
        .name  = "fuse",
@@ -885,17 +826,12 @@ static struct miscdevice fuse_miscdevice = {
 
 int __init fuse_dev_init(void)
 {
-       int err;
-       err = fuse_version_init();
-       if (err)
-               goto out;
-
-       err = -ENOMEM;
+       int err = -ENOMEM;
        fuse_req_cachep = kmem_cache_create("fuser_request",
                                            sizeof(struct fuse_req),
                                            0, 0, NULL, NULL);
        if (!fuse_req_cachep)
-               goto out_version_clean;
+               goto out;
 
        err = misc_register(&fuse_miscdevice);
        if (err)
@@ -905,8 +841,6 @@ int __init fuse_dev_init(void)
 
  out_cache_clean:
        kmem_cache_destroy(fuse_req_cachep);
- out_version_clean:
-       fuse_version_clean();
  out:
        return err;
 }
@@ -915,5 +849,4 @@ void fuse_dev_cleanup(void)
 {
        misc_deregister(&fuse_miscdevice);
        kmem_cache_destroy(fuse_req_cachep);
-       fuse_version_clean();
 }
index fa0c4971cc7f63796f4c4d45134c7aa499a750e2..48211bc1a07caef9d39af31bfff2266f5c17ac24 100644 (file)
@@ -216,6 +216,7 @@ struct fuse_req {
        union {
                struct fuse_forget_in forget_in;
                struct fuse_release_in release_in;
+               struct fuse_init_in_out init_in_out;
        } misc;
 
        /** page vector */
@@ -482,3 +483,8 @@ int fuse_do_getattr(struct inode *inode);
  * Invalidate inode attributes
  */
 void fuse_invalidate_attr(struct inode *inode);
+
+/**
+ * Send the INIT message
+ */
+void fuse_send_init(struct fuse_conn *fc);
index bad4546152c135cad9eb8655ab8b8097e3de5933..d76b5d1ccff43cd331b1bb0e9198c865608f6cc5 100644 (file)
@@ -79,13 +79,13 @@ enum fuse_opcode {
        FUSE_WRITE         = 16,
        FUSE_STATFS        = 17,
        FUSE_RELEASE       = 18,
-       /*FUSE_INVALIDATE    = 19,*/
        FUSE_FSYNC         = 20,
        FUSE_SETXATTR      = 21,
        FUSE_GETXATTR      = 22,
        FUSE_LISTXATTR     = 23,
        FUSE_REMOVEXATTR   = 24,
        FUSE_FLUSH         = 25,
+       FUSE_INIT          = 26
 };
 
 /* Conservative buffer size for the client */
@@ -201,6 +201,11 @@ struct fuse_getxattr_out {
        __u32   size;
 };
 
+struct fuse_init_in_out {
+       __u32   major;
+       __u32   minor;
+};
+
 struct fuse_in_header {
        __u32   len;
        __u32   opcode;
index eb40b7b7c2d8a1523517f3fc5e25d4bc1b4bf1c3..8227be8a0013a1f11c0660744cbec1904404dfa0 100644 (file)
@@ -478,14 +478,13 @@ static struct fuse_conn *new_conn(void)
                INIT_LIST_HEAD(&fc->pending);
                INIT_LIST_HEAD(&fc->processing);
                INIT_LIST_HEAD(&fc->unused_list);
-               sema_init(&fc->outstanding_sem, FUSE_MAX_OUTSTANDING);
+               sema_init(&fc->outstanding_sem, 0);
                for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) {
                        struct fuse_req *req = fuse_request_alloc();
                        if (!req) {
                                free_conn(fc);
                                return NULL;
                        }
-                       req->preallocated = 1;
                        list_add(&req->list, &fc->unused_list);
                }
 #ifdef KERNEL_2_6
@@ -668,7 +667,7 @@ static int fuse_read_super(struct super_block *sb, void *data, int silent)
                iput(root);
                goto err;
        }
-
+       fuse_send_init(fc);
        return 0;
 
  err:
index b5be472384b65db03a256f77b8e5ced60da83d89..1a6c56edadf4c98c62315dd5079783e2a07fe5da 100644 (file)
@@ -99,6 +99,7 @@ static const char *opname(enum fuse_opcode opcode)
     case FUSE_GETXATTR:                return "GETXATTR";
     case FUSE_LISTXATTR:       return "LISTXATTR";
     case FUSE_REMOVEXATTR:     return "REMOVEXATTR";
+    case FUSE_INIT:            return "INIT";
     default:                   return "???";
     }
 }
@@ -1504,6 +1505,20 @@ static void do_removexattr(struct fuse *f, struct fuse_in_header *in,
     send_reply(f, in, res, NULL, 0);
 }
 
+static void do_init(struct fuse *f, struct fuse_in_header *in,
+                    struct fuse_init_in_out *arg)
+{
+    struct fuse_init_in_out outarg;
+    if (f->flags & FUSE_DEBUG) {
+        printf("   INIT: %u.%u\n", arg->major, arg->minor);
+        fflush(stdout);
+    }
+    f->got_init = 1;
+    memset(&outarg, 0, sizeof(outarg));
+    outarg.major = FUSE_KERNEL_VERSION;
+    outarg.minor = FUSE_KERNEL_MINOR_VERSION;
+    send_reply(f, in, 0, &outarg, sizeof(outarg));
+}
 
 static void free_cmd(struct fuse_cmd *cmd)
 {
@@ -1527,6 +1542,12 @@ void fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd)
         fflush(stdout);
     }
 
+    if (!f->got_init && in->opcode != FUSE_INIT) {
+        /* Old kernel version probably */
+        send_reply(f, in, -EPROTO, NULL, 0);
+        goto out;
+    }
+
     ctx->fuse = f;
     ctx->uid = in->uid;
     ctx->gid = in->gid;
@@ -1628,10 +1649,15 @@ void fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd)
         do_removexattr(f, in, (char *) inarg);
         break;
 
+    case FUSE_INIT:
+        do_init(f, in, (struct fuse_init_in_out *) inarg);
+        break;
+
     default:
         send_reply(f, in, -ENOSYS, NULL, 0);
     }
 
+ out:
     free_cmd(cmd);
 }
 
@@ -1742,47 +1768,6 @@ void fuse_set_getcontext_func(struct fuse_context *(*func)(void))
     fuse_getcontext = func;
 }
 
-static int check_version(struct fuse *f)
-{
-    int res;
-    const char *version_file = FUSE_VERSION_FILE_NEW;
-    FILE *vf = fopen(version_file, "r");
-    if (vf == NULL) {
-        version_file = FUSE_VERSION_FILE_OLD;
-        vf = fopen(version_file, "r");
-        if (vf == NULL) {
-            struct stat tmp;
-            if (stat(FUSE_DEV_OLD, &tmp) != -1) {
-                fprintf(stderr, "fuse: kernel interface too old, need >= %i.%i\n",
-                        FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
-                return -1;
-            } else {
-                fprintf(stderr, "fuse: warning: version of kernel interface unknown\n");
-                return 0;
-            }
-        }
-    }
-    res = fscanf(vf, "%i.%i", &f->majorver, &f->minorver);
-    fclose(vf);
-    if (res != 2) {
-        fprintf(stderr, "fuse: error reading %s\n", version_file);
-        return -1;
-    }
-    if (f->majorver != FUSE_KERNEL_VERSION) {
-        fprintf(stderr, "fuse: bad kernel interface major version: needs %i\n",
-                FUSE_KERNEL_VERSION);
-        return -1;
-    }
-    if (f->minorver < FUSE_KERNEL_MINOR_VERSION_NEED) {
-        fprintf(stderr, "fuse: kernel interface too old: need >= %i.%i\n",
-                FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
-        return -1;
-    }    
-    
-    return 0;
-}
-
-
 int fuse_is_lib_option(const char *opt)
 {
     if (strcmp(opt, "debug") == 0 ||
@@ -1838,9 +1823,6 @@ struct fuse *fuse_new_common(int fd, const char *opts,
         goto out;
     }
 
-    if (check_version(f) == -1)
-        goto out_free;
-
     if (parse_lib_opts(f, opts) == -1)
         goto out_free;
 
index ebe712a9e9d34251042d1a26411071706be465a5..284e531ca8fd61bc57381bf3ba0c03ddc8dc19fd 100644 (file)
@@ -28,8 +28,7 @@ struct fuse {
     int numworker;
     int numavail;
     volatile int exited;
-    int majorver;
-    int minorver;
+    int got_init;
 };
 
 struct fuse *fuse_new_common(int fd, const char *opts,
index 80808c8fc4deed5d3f56e427dfa24c09067780a5..0686d7aeaaa30db8a5fe670527a6c1af55ced9e3 100644 (file)
@@ -40,7 +40,6 @@
 #define FUSE_DEV_OLD "/proc/fs/fuse/dev"
 #define FUSE_DEV_NEW "/dev/fuse"
 #define FUSE_VERSION_FILE_OLD "/proc/fs/fuse/version"
-#define FUSE_VERSION_FILE_NEW "/sys/fs/fuse/version"
 #define FUSE_MAJOR 10
 #define FUSE_MINOR 229
 
@@ -532,24 +531,16 @@ static int check_version(const char *dev)
     int majorver;
     int minorver;
     const char *version_file;
-    int isold = 0;
     FILE *vf;
 
-    if (strcmp(dev, FUSE_DEV_OLD) == 0)
-        isold = 1;
+    if (strcmp(dev, FUSE_DEV_OLD) != 0)
+        return 0;
 
-    version_file = FUSE_VERSION_FILE_NEW;
+    version_file = FUSE_VERSION_FILE_OLD;
     vf = fopen(version_file, "r");
     if (vf == NULL) {
-        version_file = FUSE_VERSION_FILE_OLD;
-        vf = fopen(version_file, "r");
-        if (vf == NULL) {
-            if (isold) {
-                fprintf(stderr, "%s: kernel interface too old\n", progname);
-                return -1;
-            } else
-                return 0;
-        }
+        fprintf(stderr, "%s: kernel interface too old\n", progname);
+        return -1;
     }
     res = fscanf(vf, "%i.%i", &majorver, &minorver);
     fclose(vf);
@@ -557,7 +548,7 @@ static int check_version(const char *dev)
         fprintf(stderr, "%s: error reading %s\n", progname, version_file);
         return -1;
     }
-    if (majorver < 3) {
+     if (majorver < 3) {
         fprintf(stderr, "%s: kernel interface too old\n", progname);
         return -1;
     }