* Clarify how the protocol version should be negotiated between
authorMiklos Szeredi <miklos@szeredi.hu>
Thu, 16 Jul 2009 11:07:31 +0000 (11:07 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Thu, 16 Jul 2009 11:07:31 +0000 (11:07 +0000)
kernel and userspace.  Notably libfuse didn't correctly handle the
case when the supported major versions didn't match

ChangeLog
include/fuse_kernel.h
lib/fuse_lowlevel.c

index fc0b51f183165fade3c9ca00954cba38a26fbefb..c207b2371b2c3bbd9f14731af17723ac2bb5a40e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2009-07-16  Miklos Szeredi <miklos@szeredi.hu>
+
+       * Clarify how the protocol version should be negotiated between
+       kernel and userspace.  Notably libfuse didn't correctly handle the
+       case when the supported major versions didn't match
+
 2009-07-02  Miklos Szeredi <miklos@szeredi.hu>
 
        * The context is extended with a 'umask' field.  The umask is sent
index dac35d8b9b19dec3c40ab9d48002e0d38a28262a..bd736307daed5ab27a122d272436c0d62839c1ad 100644 (file)
 #define __u32 uint32_t
 #define __s32 int32_t
 
+/*
+ * Version negotiation:
+ *
+ * Both the kernel and userspace send the version they support in the
+ * INIT request and reply respectively.
+ *
+ * If the major versions match then both shall use the smallest
+ * of the two minor versions for communication.
+ *
+ * If the kernel supports a larger major version, then userspace shall
+ * reply with the major version it supports, ignore the rest of the
+ * INIT message and expect a new INIT message from the kernel with a
+ * matching major version.
+ *
+ * If the library supports a larger major version, then it shall fall
+ * back to the major protocol version sent by the kernel for
+ * communication and reply with that major version (and an arbitrary
+ * supported minor version).
+ */
+
 /** Version number of this interface */
 #define FUSE_KERNEL_VERSION 7
 
index 32b9db312245672057a4429b16a375670cdd3041..c0347b3def68752d39dfc1146d950342b3ed7194 100644 (file)
@@ -1150,7 +1150,7 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
        (void) nodeid;
        if (f->debug) {
                fprintf(stderr, "INIT: %u.%u\n", arg->major, arg->minor);
-               if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
+               if (arg->major == 7 && arg->minor >= 6) {
                        fprintf(stderr, "flags=0x%08x\n", arg->flags);
                        fprintf(stderr, "max_readahead=0x%08x\n",
                                arg->max_readahead);
@@ -1161,6 +1161,10 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
        f->conn.capable = 0;
        f->conn.want = 0;
 
+       memset(&outarg, 0, sizeof(outarg));
+       outarg.major = FUSE_KERNEL_VERSION;
+       outarg.minor = FUSE_KERNEL_MINOR_VERSION;
+
        if (arg->major < 7) {
                fprintf(stderr, "fuse: unsupported protocol version: %u.%u\n",
                        arg->major, arg->minor);
@@ -1168,7 +1172,13 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
                return;
        }
 
-       if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
+       if (arg->major > 7) {
+               /* Wait for a second INIT request with a 7.X version */
+               send_reply_ok(req, &outarg, sizeof(outarg));
+               return;
+       }
+
+       if (arg->minor >= 6) {
                if (f->conn.async_read)
                        f->conn.async_read = arg->flags & FUSE_ASYNC_READ;
                if (arg->max_readahead < f->conn.max_readahead)
@@ -1211,9 +1221,6 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
        if (f->op.init)
                f->op.init(f->userdata, &f->conn);
 
-       memset(&outarg, 0, sizeof(outarg));
-       outarg.major = FUSE_KERNEL_VERSION;
-       outarg.minor = FUSE_KERNEL_MINOR_VERSION;
        if (f->conn.async_read || (f->conn.want & FUSE_CAP_ASYNC_READ))
                outarg.flags |= FUSE_ASYNC_READ;
        if (f->conn.want & FUSE_CAP_POSIX_LOCKS)