[PATCH] fuse: make maximum write data configurable
authorMiklos Szeredi <miklos@szeredi.hu>
Fri, 6 Jan 2006 08:19:41 +0000 (00:19 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Fri, 6 Jan 2006 16:33:56 +0000 (08:33 -0800)
Make the maximum size of write data configurable by the filesystem.  The
previous fixed 4096 limit only worked on architectures where the page size is
less or equal to this.  This change make writing work on other architectures
too, and also lets the filesystem receive bigger write requests in direct_io
mode.

Normal writes which go through the page cache are still limited to a page
sized chunk per request.

Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/fuse/dev.c
fs/fuse/fuse_i.h
fs/fuse/inode.c
include/linux/fuse.h

index 1afdffdf80db73a16656607c3972902d6f00b745..e08ab4702d97ca1099474c2833778d9e72c879b4 100644 (file)
@@ -148,6 +148,26 @@ void fuse_release_background(struct fuse_req *req)
        spin_unlock(&fuse_lock);
 }
 
+static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
+{
+       int i;
+       struct fuse_init_out *arg = &req->misc.init_out;
+
+       if (arg->major != FUSE_KERNEL_VERSION)
+               fc->conn_error = 1;
+       else {
+               fc->minor = arg->minor;
+               fc->max_write = arg->minor < 5 ? 4096 : arg->max_write;
+       }
+
+       /* After INIT reply is received other requests can go
+          out.  So do (FUSE_MAX_OUTSTANDING - 1) number of
+          up()s on outstanding_sem.  The last up() is done in
+          fuse_putback_request() */
+       for (i = 1; i < FUSE_MAX_OUTSTANDING; i++)
+               up(&fc->outstanding_sem);
+}
+
 /*
  * This function is called when a request is finished.  Either a reply
  * has arrived or it was interrupted (and not yet sent) or some error
@@ -172,21 +192,9 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
                up_read(&fc->sbput_sem);
        }
        wake_up(&req->waitq);
-       if (req->in.h.opcode == FUSE_INIT) {
-               int i;
-
-               if (req->misc.init_in_out.major != FUSE_KERNEL_VERSION)
-                       fc->conn_error = 1;
-
-               fc->minor = req->misc.init_in_out.minor;
-
-               /* After INIT reply is received other requests can go
-                  out.  So do (FUSE_MAX_OUTSTANDING - 1) number of
-                  up()s on outstanding_sem.  The last up() is done in
-                  fuse_putback_request() */
-               for (i = 1; i < FUSE_MAX_OUTSTANDING; i++)
-                       up(&fc->outstanding_sem);
-       } else if (req->in.h.opcode == FUSE_RELEASE && req->inode == NULL) {
+       if (req->in.h.opcode == FUSE_INIT)
+               process_init_reply(fc, req);
+       else if (req->in.h.opcode == FUSE_RELEASE && req->inode == NULL) {
                /* Special case for failed iget in CREATE */
                u64 nodeid = req->in.h.nodeid;
                __fuse_get_request(req);
@@ -359,7 +367,7 @@ 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;
+       struct fuse_init_in *arg = &req->misc.init_in;
        arg->major = FUSE_KERNEL_VERSION;
        arg->minor = FUSE_KERNEL_MINOR_VERSION;
        req->in.h.opcode = FUSE_INIT;
@@ -367,8 +375,12 @@ void fuse_send_init(struct fuse_conn *fc)
        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;
+       /* Variable length arguement used for backward compatibility
+          with interface version < 7.5.  Rest of init_out is zeroed
+          by do_get_request(), so a short reply is not a problem */
+       req->out.argvar = 1;
+       req->out.args[0].size = sizeof(struct fuse_init_out);
+       req->out.args[0].value = &req->misc.init_out;
        request_send_background(fc, req);
 }
 
index 17fd368559cdd33554a657d66761737514bcb263..74c8d098a14a2b9ced4faca1c940f804d39cd19f 100644 (file)
@@ -21,9 +21,6 @@
 /** If more requests are outstanding, then the operation will block */
 #define FUSE_MAX_OUTSTANDING 10
 
-/** Maximum size of data in a write request */
-#define FUSE_MAX_WRITE 4096
-
 /** It could be as large as PATH_MAX, but would that have any uses? */
 #define FUSE_NAME_MAX 1024
 
@@ -162,7 +159,8 @@ struct fuse_req {
        union {
                struct fuse_forget_in forget_in;
                struct fuse_release_in release_in;
-               struct fuse_init_in_out init_in_out;
+               struct fuse_init_in init_in;
+               struct fuse_init_out init_out;
        } misc;
 
        /** page vector */
index 3580b9e12345e6b6b1b1eb03cac132e2ecaf2d05..e4541869831e2348b664235fd465b4410174864e 100644 (file)
@@ -485,7 +485,6 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
        fc->max_read = d.max_read;
        if (fc->max_read / PAGE_CACHE_SIZE < fc->bdi.ra_pages)
                fc->bdi.ra_pages = fc->max_read / PAGE_CACHE_SIZE;
-       fc->max_write = FUSE_MAX_WRITE;
 
        err = -ENOMEM;
        root = get_root_inode(sb, d.rootmode);
index 8f64cc2205b092099387a8e034cfba3ca8a47c1d..528959c52f1b6fd5f9f3f9722f22cfe6616876e1 100644 (file)
@@ -14,7 +14,7 @@
 #define FUSE_KERNEL_VERSION 7
 
 /** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 4
+#define FUSE_KERNEL_MINOR_VERSION 5
 
 /** The node ID of the root inode */
 #define FUSE_ROOT_ID 1
@@ -244,11 +244,18 @@ struct fuse_access_in {
        __u32   padding;
 };
 
-struct fuse_init_in_out {
+struct fuse_init_in {
        __u32   major;
        __u32   minor;
 };
 
+struct fuse_init_out {
+       __u32   major;
+       __u32   minor;
+       __u32   unused[3];
+       __u32   max_write;
+};
+
 struct fuse_in_header {
        __u32   len;
        __u32   opcode;