2024-02-28 14:41:36

by Hou Tao

[permalink] [raw]
Subject: [PATCH v2 3/6] virtiofs: factor out more common methods for argbuf

From: Hou Tao <[email protected]>

Factor out more common methods for bounce buffer of fuse args:

1) virtio_fs_argbuf_setup_sg: set-up sgs for bounce buffer
2) virtio_fs_argbuf_copy_from_in_arg: copy each in-arg to bounce buffer
3) virtio_fs_argbuf_out_args_offset: calc the start offset of out-arg
4) virtio_fs_argbuf_copy_to_out_arg: copy bounce buffer to each out-arg

These methods will be used to implement bounce buffer backed by
scattered pages which are allocated separatedly.

Signed-off-by: Hou Tao <[email protected]>
---
fs/fuse/virtio_fs.c | 77 +++++++++++++++++++++++++++++++++++----------
1 file changed, 60 insertions(+), 17 deletions(-)

diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
index cd1330506daba..f10fff7f23a0f 100644
--- a/fs/fuse/virtio_fs.c
+++ b/fs/fuse/virtio_fs.c
@@ -86,6 +86,10 @@ struct virtio_fs_req_work {
struct work_struct done_work;
};

+struct virtio_fs_argbuf {
+ DECLARE_FLEX_ARRAY(u8, buf);
+};
+
static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq,
struct fuse_req *req, bool in_flight);

@@ -404,13 +408,15 @@ static void virtio_fs_request_dispatch_work(struct work_struct *work)
}
}

-static void virtio_fs_argbuf_free(void *argbuf)
+static void virtio_fs_argbuf_free(struct virtio_fs_argbuf *argbuf)
{
kfree(argbuf);
}

-static void *virtio_fs_argbuf_new(struct fuse_args *args, gfp_t gfp)
+static struct virtio_fs_argbuf *virtio_fs_argbuf_new(struct fuse_args *args,
+ gfp_t gfp)
{
+ struct virtio_fs_argbuf *argbuf;
unsigned int numargs;
unsigned int len;

@@ -419,7 +425,41 @@ static void *virtio_fs_argbuf_new(struct fuse_args *args, gfp_t gfp)
numargs = args->out_numargs - args->out_pages;
len += fuse_len_args(numargs, args->out_args);

- return kmalloc(len, gfp);
+ argbuf = kmalloc(struct_size(argbuf, buf, len), gfp);
+
+ return argbuf;
+}
+
+static unsigned int virtio_fs_argbuf_setup_sg(struct virtio_fs_argbuf *argbuf,
+ unsigned int offset,
+ unsigned int len,
+ struct scatterlist *sg)
+{
+ sg_init_one(sg, argbuf->buf + offset, len);
+ return 1;
+}
+
+static void virtio_fs_argbuf_copy_from_in_arg(struct virtio_fs_argbuf *argbuf,
+ unsigned int offset,
+ const void *src, unsigned int len)
+{
+ memcpy(argbuf->buf + offset, src, len);
+}
+
+static unsigned int
+virtio_fs_argbuf_out_args_offset(struct virtio_fs_argbuf *argbuf,
+ const struct fuse_args *args)
+{
+ unsigned int num_in = args->in_numargs - args->in_pages;
+
+ return fuse_len_args(num_in, (struct fuse_arg *)args->in_args);
+}
+
+static void virtio_fs_argbuf_copy_to_out_arg(struct virtio_fs_argbuf *argbuf,
+ unsigned int offset, void *dst,
+ unsigned int len)
+{
+ memcpy(dst, argbuf->buf + offset, len);
}

/*
@@ -515,9 +555,9 @@ static void copy_args_to_argbuf(struct fuse_req *req)

num_in = args->in_numargs - args->in_pages;
for (i = 0; i < num_in; i++) {
- memcpy(req->argbuf + offset,
- args->in_args[i].value,
- args->in_args[i].size);
+ virtio_fs_argbuf_copy_from_in_arg(req->argbuf, offset,
+ args->in_args[i].value,
+ args->in_args[i].size);
offset += args->in_args[i].size;
}
}
@@ -525,17 +565,19 @@ static void copy_args_to_argbuf(struct fuse_req *req)
/* Copy args out of req->argbuf */
static void copy_args_from_argbuf(struct fuse_args *args, struct fuse_req *req)
{
+ struct virtio_fs_argbuf *argbuf;
unsigned int remaining;
unsigned int offset;
- unsigned int num_in;
unsigned int num_out;
unsigned int i;

remaining = req->out.h.len - sizeof(req->out.h);
- num_in = args->in_numargs - args->in_pages;
num_out = args->out_numargs - args->out_pages;
- offset = fuse_len_args(num_in, (struct fuse_arg *)args->in_args);
+ if (!num_out)
+ goto out;

+ argbuf = req->argbuf;
+ offset = virtio_fs_argbuf_out_args_offset(argbuf, args);
for (i = 0; i < num_out; i++) {
unsigned int argsize = args->out_args[i].size;

@@ -545,13 +587,16 @@ static void copy_args_from_argbuf(struct fuse_args *args, struct fuse_req *req)
argsize = remaining;
}

- memcpy(args->out_args[i].value, req->argbuf + offset, argsize);
+ virtio_fs_argbuf_copy_to_out_arg(argbuf, offset,
+ args->out_args[i].value,
+ argsize);
offset += argsize;

if (i != args->out_numargs - 1)
remaining -= argsize;
}

+out:
/* Store the actual size of the variable-length arg */
if (args->out_argvar)
args->out_args[args->out_numargs - 1].size = remaining;
@@ -1100,7 +1145,6 @@ static unsigned int sg_init_fuse_args(struct scatterlist *sg,
struct fuse_arg *args,
unsigned int numargs,
bool argpages,
- void *argbuf,
unsigned int *len_used)
{
struct fuse_args_pages *ap = container_of(req->args, typeof(*ap), args);
@@ -1109,7 +1153,8 @@ static unsigned int sg_init_fuse_args(struct scatterlist *sg,

len = fuse_len_args(numargs - argpages, args);
if (len)
- sg_init_one(&sg[total_sgs++], argbuf, len);
+ total_sgs += virtio_fs_argbuf_setup_sg(req->argbuf, *len_used,
+ len, &sg[total_sgs]);

if (argpages)
total_sgs += sg_init_fuse_pages(&sg[total_sgs],
@@ -1117,8 +1162,7 @@ static unsigned int sg_init_fuse_args(struct scatterlist *sg,
ap->num_pages,
args[numargs - 1].size);

- if (len_used)
- *len_used = len;
+ *len_used = len;

return total_sgs;
}
@@ -1168,7 +1212,7 @@ static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq,
out_sgs += sg_init_fuse_args(&sg[out_sgs], req,
(struct fuse_arg *)args->in_args,
args->in_numargs, args->in_pages,
- req->argbuf, &argbuf_used);
+ &argbuf_used);

/* Reply elements */
if (test_bit(FR_ISREPLY, &req->flags)) {
@@ -1176,8 +1220,7 @@ static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq,
&req->out.h, sizeof(req->out.h));
in_sgs += sg_init_fuse_args(&sg[out_sgs + in_sgs], req,
args->out_args, args->out_numargs,
- args->out_pages,
- req->argbuf + argbuf_used, NULL);
+ args->out_pages, &argbuf_used);
}

WARN_ON(out_sgs + in_sgs != total_sgs);
--
2.29.2



2024-03-01 14:25:22

by Miklos Szeredi

[permalink] [raw]
Subject: Re: [PATCH v2 3/6] virtiofs: factor out more common methods for argbuf

On Wed, 28 Feb 2024 at 15:41, Hou Tao <[email protected]> wrote:
>
> From: Hou Tao <[email protected]>
>
> Factor out more common methods for bounce buffer of fuse args:
>
> 1) virtio_fs_argbuf_setup_sg: set-up sgs for bounce buffer
> 2) virtio_fs_argbuf_copy_from_in_arg: copy each in-arg to bounce buffer
> 3) virtio_fs_argbuf_out_args_offset: calc the start offset of out-arg
> 4) virtio_fs_argbuf_copy_to_out_arg: copy bounce buffer to each out-arg
>
> These methods will be used to implement bounce buffer backed by
> scattered pages which are allocated separatedly.

Why is req->argbuf not changed to being typed?

Thanks,
Miklos

2024-03-09 04:28:02

by Hou Tao

[permalink] [raw]
Subject: Re: [PATCH v2 3/6] virtiofs: factor out more common methods for argbuf

Hi,

On 3/1/2024 10:24 PM, Miklos Szeredi wrote:
> On Wed, 28 Feb 2024 at 15:41, Hou Tao <[email protected]> wrote:
>> From: Hou Tao <[email protected]>
>>
>> Factor out more common methods for bounce buffer of fuse args:
>>
>> 1) virtio_fs_argbuf_setup_sg: set-up sgs for bounce buffer
>> 2) virtio_fs_argbuf_copy_from_in_arg: copy each in-arg to bounce buffer
>> 3) virtio_fs_argbuf_out_args_offset: calc the start offset of out-arg
>> 4) virtio_fs_argbuf_copy_to_out_arg: copy bounce buffer to each out-arg
>>
>> These methods will be used to implement bounce buffer backed by
>> scattered pages which are allocated separatedly.
> Why is req->argbuf not changed to being typed?

Will update in next revision. Thanks for the suggestion.
>
> Thanks,
> Miklos