fuse: stop copying args to fuse_req
authorMiklos Szeredi <mszeredi@redhat.com>
Tue, 10 Sep 2019 13:04:11 +0000 (15:04 +0200)
committerMiklos Szeredi <mszeredi@redhat.com>
Tue, 10 Sep 2019 14:29:50 +0000 (16:29 +0200)
No need to duplicate the argument arrays in fuse_req, so just dereference
req->args instead of copying to the fuse_req internal ones.

This allows further cleanup of the fuse_req structure.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/fuse/dev.c
fs/fuse/fuse_i.h

index f240d54..dfc0658 100644 (file)
@@ -202,7 +202,8 @@ static unsigned int fuse_req_hash(u64 unique)
 static void queue_request(struct fuse_iqueue *fiq, struct fuse_req *req)
 {
        req->in.h.len = sizeof(struct fuse_in_header) +
-               len_args(req->in.numargs, (struct fuse_arg *) req->in.args);
+               len_args(req->args->in_numargs,
+                        (struct fuse_arg *) req->args->in_args);
        list_add_tail(&req->list, &fiq->pending);
        wake_up(&fiq->waitq);
        kill_fasync(&fiq->fasync, SIGIO, POLL_IN);
@@ -257,6 +258,7 @@ static void flush_bg_queue(struct fuse_conn *fc)
 static void request_end(struct fuse_conn *fc, struct fuse_req *req)
 {
        struct fuse_iqueue *fiq = &fc->iq;
+       bool async = req->args->end;
 
        if (test_and_set_bit(FR_FINISHED, &req->flags))
                goto put_request;
@@ -302,8 +304,8 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
                wake_up(&req->waitq);
        }
 
-       if (req->end)
-               req->end(fc, req);
+       if (async)
+               req->args->end(fc, req->args, req->out.h.error);
 put_request:
        fuse_put_request(fc, req);
 }
@@ -450,25 +452,12 @@ void fuse_args_to_req(struct fuse_req *req, struct fuse_args *args)
 
        req->in.h.opcode = args->opcode;
        req->in.h.nodeid = args->nodeid;
-       req->in.numargs = args->in_numargs;
-       memcpy(req->in.args, args->in_args,
-              args->in_numargs * sizeof(struct fuse_in_arg));
-       req->out.argvar = args->out_argvar;
-       req->out.numargs = args->out_numargs;
-       memcpy(req->out.args, args->out_args,
-              args->out_numargs * sizeof(struct fuse_arg));
-
        if (args->in_pages || args->out_pages) {
-               req->in.argpages = args->in_pages;
-               req->out.argpages = args->out_pages;
-               req->out.page_zeroing = args->page_zeroing;
-               req->out.page_replace = args->page_replace;
-
                req->pages = ap->pages;
                req->page_descs = ap->descs;
                req->num_pages = ap->num_pages;
        }
-
+       req->args = args;
 }
 
 ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args)
@@ -502,7 +491,7 @@ ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args)
        ret = req->out.h.error;
        if (!ret && args->out_argvar) {
                BUG_ON(args->out_numargs == 0);
-               ret = req->out.args[args->out_numargs - 1].size;
+               ret = args->out_args[args->out_numargs - 1].size;
        }
        fuse_put_request(fc, req);
 
@@ -538,19 +527,6 @@ static bool fuse_request_queue_background(struct fuse_conn *fc,
        return queued;
 }
 
-static void fuse_simple_end(struct fuse_conn *fc, struct fuse_req *req)
-{
-       struct fuse_args *args = req->args;
-       int err = req->out.h.error;
-
-       if (!err && args->out_argvar) {
-               BUG_ON(args->out_numargs == 0);
-               args->out_args[args->out_numargs - 1].size =
-                       req->out.args[args->out_numargs - 1].size;
-       }
-       req->args->end(fc, req->args, req->out.h.error);
-}
-
 int fuse_simple_background(struct fuse_conn *fc, struct fuse_args *args,
                            gfp_t gfp_flags)
 {
@@ -571,9 +547,6 @@ int fuse_simple_background(struct fuse_conn *fc, struct fuse_args *args,
 
        fuse_args_to_req(req, args);
 
-       req->args = args;
-       req->end = fuse_simple_end;
-
        if (!fuse_request_queue_background(fc, req)) {
                fuse_put_request(fc, req);
                return -ENOTCONN;
@@ -598,8 +571,6 @@ static int fuse_simple_notify_reply(struct fuse_conn *fc,
        req->in.h.unique = unique;
 
        fuse_args_to_req(req, args);
-       req->args = args;
-       req->end = fuse_simple_end;
 
        spin_lock(&fiq->lock);
        if (fiq->connected) {
@@ -1197,7 +1168,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
        struct fuse_iqueue *fiq = &fc->iq;
        struct fuse_pqueue *fpq = &fud->pq;
        struct fuse_req *req;
-       struct fuse_in *in;
+       struct fuse_args *args;
        unsigned reqsize;
        unsigned int hash;
 
@@ -1258,14 +1229,14 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
        list_del_init(&req->list);
        spin_unlock(&fiq->lock);
 
-       in = &req->in;
-       reqsize = in->h.len;
+       args = req->args;
+       reqsize = req->in.h.len;
 
        /* If request is too large, reply with an error and restart the read */
        if (nbytes < reqsize) {
                req->out.h.error = -EIO;
                /* SETXATTR is special, since it may contain too large data */
-               if (in->h.opcode == FUSE_SETXATTR)
+               if (args->opcode == FUSE_SETXATTR)
                        req->out.h.error = -E2BIG;
                request_end(fc, req);
                goto restart;
@@ -1274,10 +1245,10 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
        list_add(&req->list, &fpq->io);
        spin_unlock(&fpq->lock);
        cs->req = req;
-       err = fuse_copy_one(cs, &in->h, sizeof(in->h));
+       err = fuse_copy_one(cs, &req->in.h, sizeof(req->in.h));
        if (!err)
-               err = fuse_copy_args(cs, in->numargs, in->argpages,
-                                    (struct fuse_arg *) in->args, 0);
+               err = fuse_copy_args(cs, args->in_numargs, args->in_pages,
+                                    (struct fuse_arg *) args->in_args, 0);
        fuse_copy_finish(cs);
        spin_lock(&fpq->lock);
        clear_bit(FR_LOCKED, &req->flags);
@@ -1808,27 +1779,25 @@ static struct fuse_req *request_find(struct fuse_pqueue *fpq, u64 unique)
        return NULL;
 }
 
-static int copy_out_args(struct fuse_copy_state *cs, struct fuse_out *out,
+static int copy_out_args(struct fuse_copy_state *cs, struct fuse_args *args,
                         unsigned nbytes)
 {
        unsigned reqsize = sizeof(struct fuse_out_header);
 
-       if (out->h.error)
-               return nbytes != reqsize ? -EINVAL : 0;
-
-       reqsize += len_args(out->numargs, out->args);
+       reqsize += len_args(args->out_numargs, args->out_args);
 
-       if (reqsize < nbytes || (reqsize > nbytes && !out->argvar))
+       if (reqsize < nbytes || (reqsize > nbytes && !args->out_argvar))
                return -EINVAL;
        else if (reqsize > nbytes) {
-               struct fuse_arg *lastarg = &out->args[out->numargs-1];
+               struct fuse_arg *lastarg = &args->out_args[args->out_numargs-1];
                unsigned diffsize = reqsize - nbytes;
+
                if (diffsize > lastarg->size)
                        return -EINVAL;
                lastarg->size -= diffsize;
        }
-       return fuse_copy_args(cs, out->numargs, out->argpages, out->args,
-                             out->page_zeroing);
+       return fuse_copy_args(cs, args->out_numargs, args->out_pages,
+                             args->out_args, args->page_zeroing);
 }
 
 /*
@@ -1907,10 +1876,13 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud,
        set_bit(FR_LOCKED, &req->flags);
        spin_unlock(&fpq->lock);
        cs->req = req;
-       if (!req->out.page_replace)
+       if (!req->args->page_replace)
                cs->move_pages = 0;
 
-       err = copy_out_args(cs, &req->out, nbytes);
+       if (oh.error)
+               err = nbytes != sizeof(oh) ? -EINVAL : 0;
+       else
+               err = copy_out_args(cs, req->args, nbytes);
        fuse_copy_finish(cs);
 
        spin_lock(&fpq->lock);
index a81fdbe..9454f23 100644 (file)
@@ -224,57 +224,12 @@ struct fuse_in_arg {
        const void *value;
 };
 
-/** The request input */
-struct fuse_in {
-       /** The request header */
-       struct fuse_in_header h;
-
-       /** True if the data for the last argument is in req->pages */
-       unsigned argpages:1;
-
-       /** Number of arguments */
-       unsigned numargs;
-
-       /** Array of arguments */
-       struct fuse_in_arg args[3];
-};
-
 /** One output argument of a request */
 struct fuse_arg {
        unsigned size;
        void *value;
 };
 
-/** The request output */
-struct fuse_out {
-       /** Header returned from userspace */
-       struct fuse_out_header h;
-
-       /*
-        * The following bitfields are not changed during the request
-        * processing
-        */
-
-       /** Last argument is variable length (can be shorter than
-           arg->size) */
-       unsigned argvar:1;
-
-       /** Last argument is a list of pages to copy data to */
-       unsigned argpages:1;
-
-       /** Zero partially or not copied pages */
-       unsigned page_zeroing:1;
-
-       /** Pages may be replaced with new ones */
-       unsigned page_replace:1;
-
-       /** Number or arguments */
-       unsigned numargs;
-
-       /** Array of arguments */
-       struct fuse_arg args[2];
-};
-
 /** FUSE page descriptor */
 struct fuse_page_desc {
        unsigned int length;
@@ -385,11 +340,15 @@ struct fuse_req {
        /* Request flags, updated with test/set/clear_bit() */
        unsigned long flags;
 
-       /** The request input */
-       struct fuse_in in;
+       /* The request input header */
+       struct {
+               struct fuse_in_header h;
+       } in;
 
-       /** The request output */
-       struct fuse_out out;
+       /* The request output header */
+       struct {
+               struct fuse_out_header h;
+       } out;
 
        /** Used to wake up the task waiting for completion of request*/
        wait_queue_head_t waitq;
@@ -403,9 +362,6 @@ struct fuse_req {
        /** number of pages in vector */
        unsigned num_pages;
 
-       /** Request completion callback */
-       void (*end)(struct fuse_conn *, struct fuse_req *);
-
 };
 
 struct fuse_iqueue {