Commit d4993774 authored by Miklos Szeredi's avatar Miklos Szeredi

fuse: stop copying args to fuse_req

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: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent 145b673b
...@@ -202,7 +202,8 @@ static unsigned int fuse_req_hash(u64 unique) ...@@ -202,7 +202,8 @@ static unsigned int fuse_req_hash(u64 unique)
static void queue_request(struct fuse_iqueue *fiq, struct fuse_req *req) static void queue_request(struct fuse_iqueue *fiq, struct fuse_req *req)
{ {
req->in.h.len = sizeof(struct fuse_in_header) + 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); list_add_tail(&req->list, &fiq->pending);
wake_up(&fiq->waitq); wake_up(&fiq->waitq);
kill_fasync(&fiq->fasync, SIGIO, POLL_IN); kill_fasync(&fiq->fasync, SIGIO, POLL_IN);
...@@ -257,6 +258,7 @@ static void flush_bg_queue(struct fuse_conn *fc) ...@@ -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) static void request_end(struct fuse_conn *fc, struct fuse_req *req)
{ {
struct fuse_iqueue *fiq = &fc->iq; struct fuse_iqueue *fiq = &fc->iq;
bool async = req->args->end;
if (test_and_set_bit(FR_FINISHED, &req->flags)) if (test_and_set_bit(FR_FINISHED, &req->flags))
goto put_request; goto put_request;
...@@ -302,8 +304,8 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) ...@@ -302,8 +304,8 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
wake_up(&req->waitq); wake_up(&req->waitq);
} }
if (req->end) if (async)
req->end(fc, req); req->args->end(fc, req->args, req->out.h.error);
put_request: put_request:
fuse_put_request(fc, req); fuse_put_request(fc, req);
} }
...@@ -450,25 +452,12 @@ void fuse_args_to_req(struct fuse_req *req, struct fuse_args *args) ...@@ -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.opcode = args->opcode;
req->in.h.nodeid = args->nodeid; 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) { 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->pages = ap->pages;
req->page_descs = ap->descs; req->page_descs = ap->descs;
req->num_pages = ap->num_pages; req->num_pages = ap->num_pages;
} }
req->args = args;
} }
ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_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) ...@@ -502,7 +491,7 @@ ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args)
ret = req->out.h.error; ret = req->out.h.error;
if (!ret && args->out_argvar) { if (!ret && args->out_argvar) {
BUG_ON(args->out_numargs == 0); 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); fuse_put_request(fc, req);
...@@ -538,19 +527,6 @@ static bool fuse_request_queue_background(struct fuse_conn *fc, ...@@ -538,19 +527,6 @@ static bool fuse_request_queue_background(struct fuse_conn *fc,
return queued; 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, int fuse_simple_background(struct fuse_conn *fc, struct fuse_args *args,
gfp_t gfp_flags) gfp_t gfp_flags)
{ {
...@@ -571,9 +547,6 @@ int fuse_simple_background(struct fuse_conn *fc, struct fuse_args *args, ...@@ -571,9 +547,6 @@ int fuse_simple_background(struct fuse_conn *fc, struct fuse_args *args,
fuse_args_to_req(req, args); fuse_args_to_req(req, args);
req->args = args;
req->end = fuse_simple_end;
if (!fuse_request_queue_background(fc, req)) { if (!fuse_request_queue_background(fc, req)) {
fuse_put_request(fc, req); fuse_put_request(fc, req);
return -ENOTCONN; return -ENOTCONN;
...@@ -598,8 +571,6 @@ static int fuse_simple_notify_reply(struct fuse_conn *fc, ...@@ -598,8 +571,6 @@ static int fuse_simple_notify_reply(struct fuse_conn *fc,
req->in.h.unique = unique; req->in.h.unique = unique;
fuse_args_to_req(req, args); fuse_args_to_req(req, args);
req->args = args;
req->end = fuse_simple_end;
spin_lock(&fiq->lock); spin_lock(&fiq->lock);
if (fiq->connected) { if (fiq->connected) {
...@@ -1197,7 +1168,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, ...@@ -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_iqueue *fiq = &fc->iq;
struct fuse_pqueue *fpq = &fud->pq; struct fuse_pqueue *fpq = &fud->pq;
struct fuse_req *req; struct fuse_req *req;
struct fuse_in *in; struct fuse_args *args;
unsigned reqsize; unsigned reqsize;
unsigned int hash; unsigned int hash;
...@@ -1258,14 +1229,14 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, ...@@ -1258,14 +1229,14 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
list_del_init(&req->list); list_del_init(&req->list);
spin_unlock(&fiq->lock); spin_unlock(&fiq->lock);
in = &req->in; args = req->args;
reqsize = in->h.len; reqsize = req->in.h.len;
/* If request is too large, reply with an error and restart the read */ /* If request is too large, reply with an error and restart the read */
if (nbytes < reqsize) { if (nbytes < reqsize) {
req->out.h.error = -EIO; req->out.h.error = -EIO;
/* SETXATTR is special, since it may contain too large data */ /* 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; req->out.h.error = -E2BIG;
request_end(fc, req); request_end(fc, req);
goto restart; goto restart;
...@@ -1274,10 +1245,10 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, ...@@ -1274,10 +1245,10 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
list_add(&req->list, &fpq->io); list_add(&req->list, &fpq->io);
spin_unlock(&fpq->lock); spin_unlock(&fpq->lock);
cs->req = req; 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) if (!err)
err = fuse_copy_args(cs, in->numargs, in->argpages, err = fuse_copy_args(cs, args->in_numargs, args->in_pages,
(struct fuse_arg *) in->args, 0); (struct fuse_arg *) args->in_args, 0);
fuse_copy_finish(cs); fuse_copy_finish(cs);
spin_lock(&fpq->lock); spin_lock(&fpq->lock);
clear_bit(FR_LOCKED, &req->flags); clear_bit(FR_LOCKED, &req->flags);
...@@ -1808,27 +1779,25 @@ static struct fuse_req *request_find(struct fuse_pqueue *fpq, u64 unique) ...@@ -1808,27 +1779,25 @@ static struct fuse_req *request_find(struct fuse_pqueue *fpq, u64 unique)
return NULL; 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 nbytes)
{ {
unsigned reqsize = sizeof(struct fuse_out_header); unsigned reqsize = sizeof(struct fuse_out_header);
if (out->h.error) reqsize += len_args(args->out_numargs, args->out_args);
return nbytes != reqsize ? -EINVAL : 0;
reqsize += len_args(out->numargs, out->args);
if (reqsize < nbytes || (reqsize > nbytes && !out->argvar)) if (reqsize < nbytes || (reqsize > nbytes && !args->out_argvar))
return -EINVAL; return -EINVAL;
else if (reqsize > nbytes) { 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; unsigned diffsize = reqsize - nbytes;
if (diffsize > lastarg->size) if (diffsize > lastarg->size)
return -EINVAL; return -EINVAL;
lastarg->size -= diffsize; lastarg->size -= diffsize;
} }
return fuse_copy_args(cs, out->numargs, out->argpages, out->args, return fuse_copy_args(cs, args->out_numargs, args->out_pages,
out->page_zeroing); args->out_args, args->page_zeroing);
} }
/* /*
...@@ -1907,10 +1876,13 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud, ...@@ -1907,10 +1876,13 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud,
set_bit(FR_LOCKED, &req->flags); set_bit(FR_LOCKED, &req->flags);
spin_unlock(&fpq->lock); spin_unlock(&fpq->lock);
cs->req = req; cs->req = req;
if (!req->out.page_replace) if (!req->args->page_replace)
cs->move_pages = 0; 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); fuse_copy_finish(cs);
spin_lock(&fpq->lock); spin_lock(&fpq->lock);
......
...@@ -224,57 +224,12 @@ struct fuse_in_arg { ...@@ -224,57 +224,12 @@ struct fuse_in_arg {
const void *value; 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 */ /** One output argument of a request */
struct fuse_arg { struct fuse_arg {
unsigned size; unsigned size;
void *value; 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 */ /** FUSE page descriptor */
struct fuse_page_desc { struct fuse_page_desc {
unsigned int length; unsigned int length;
...@@ -385,11 +340,15 @@ struct fuse_req { ...@@ -385,11 +340,15 @@ struct fuse_req {
/* Request flags, updated with test/set/clear_bit() */ /* Request flags, updated with test/set/clear_bit() */
unsigned long flags; unsigned long flags;
/** The request input */ /* The request input header */
struct fuse_in in; struct {
struct fuse_in_header h;
} in;
/** The request output */ /* The request output header */
struct fuse_out out; struct {
struct fuse_out_header h;
} out;
/** Used to wake up the task waiting for completion of request*/ /** Used to wake up the task waiting for completion of request*/
wait_queue_head_t waitq; wait_queue_head_t waitq;
...@@ -403,9 +362,6 @@ struct fuse_req { ...@@ -403,9 +362,6 @@ struct fuse_req {
/** number of pages in vector */ /** number of pages in vector */
unsigned num_pages; unsigned num_pages;
/** Request completion callback */
void (*end)(struct fuse_conn *, struct fuse_req *);
}; };
struct fuse_iqueue { struct fuse_iqueue {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment