From: Joanne Koong <joannelkoong@gmail.com>
To: Xiaobing Li <xiaobing.li@samsung.com>
Cc: miklos@szeredi.hu, axboe@kernel.dk, io-uring@vger.kernel.org,
linux-fsdevel@vger.kernel.org, bschubert@ddn.com,
asml.silence@gmail.com, dw@davidwei.uk, josef@toxicpanda.com,
kbusch@kernel.org, peiwei.li@samsung.com, joshi.k@samsung.com
Subject: Re: [PATCH] fuse: add zero-copy to fuse-over-io_uring
Date: Thu, 4 Dec 2025 16:26:21 -0800 [thread overview]
Message-ID: <CAJnrk1ZH9wJmdXBKjRnFEPhyocwdX=v=7tsrFjfqN1+FZqRDeQ@mail.gmail.com> (raw)
In-Reply-To: <20251204082536.17349-1-xiaobing.li@samsung.com>
On Thu, Dec 4, 2025 at 12:57 AM Xiaobing Li <xiaobing.li@samsung.com> wrote:
>
> Joanne has submitted a patch for adding a zero-copy solution.
>
> We have also done some research and testing before, and
> the test data shows improved performance. This patch is
> submitted for discussion.
Hi Xiaobing,
I think the logic in this patch uses fixed buffers for the request
payloads to reduce the per-I/O overhead of pinning/unpinning the user
pages for the payload but I don't think this helps with zero-copying,
as the pages still need to get copied from the registered buffer the
server provided back to the client's pages (or vice versa). In the
implementation in [1], the client's pages are registered into the
sparse buffer by the kernel such that the server reads/writes to those
client pages directly.
I think your patch is doing a similar thing to what the patch from
last month for registered buffers [2] did, except [2] also implemented
fixed buffers for the headers to eliminate that per-I/O overhead too.
However, when I thought about this design some more, I realized if we
used kernel-managed ring buffers instead, we pretty much get the same
wins on reducing I/O overhead but also can significantly reduce the
memory footprint used by each queue, by allowing the buffers to be
incrementally consumed and thus sharable across requests, as well as
allowing more flexibility in the future if we want to do things like
add multiple ring-pools for different categories of requests, etc.
Some more thoughts on this can be found on this thread here [3].
Thanks,
Joanne
[1] https://lore.kernel.org/linux-fsdevel/20251203003526.2889477-1-joannelkoong@gmail.com/
[2] https://lore.kernel.org/linux-fsdevel/20251027222808.2332692-9-joannelkoong@gmail.com/
[3] https://lore.kernel.org/linux-fsdevel/CAJnrk1bG7fAX8MfwJL_D2jzMNv5Rj9=1cgQvVpqC1=mGaeAwOg@mail.gmail.com/
>
> libfuse section:
> https://github.com/lreeze123/libfuse/tree/zero-copy
>
> Signed-off-by: Xiaobing Li <xiaobing.li@samsung.com>
> ---
> fs/fuse/dev_uring.c | 44 +++++++++++++++++++++++++++++++------------
> fs/fuse/dev_uring_i.h | 4 ++++
> 2 files changed, 36 insertions(+), 12 deletions(-)
>
> diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c
> index f6b12aebb8bb..23790ae78853 100644
> --- a/fs/fuse/dev_uring.c
> +++ b/fs/fuse/dev_uring.c
> @@ -584,15 +584,20 @@ static int fuse_uring_copy_from_ring(struct fuse_ring *ring,
> int err;
> struct fuse_uring_ent_in_out ring_in_out;
>
> - err = copy_from_user(&ring_in_out, &ent->headers->ring_ent_in_out,
> - sizeof(ring_in_out));
> - if (err)
> - return -EFAULT;
> + if (ent->zero_copy) {
> + iter = ent->payload_iter;
> + ring_in_out.payload_sz = ent->cmd->sqe->len;
> + } else {
> + err = copy_from_user(&ring_in_out, &ent->headers->ring_ent_in_out,
> + sizeof(ring_in_out));
> + if (err)
> + return -EFAULT;
>
> - err = import_ubuf(ITER_SOURCE, ent->payload, ring->max_payload_sz,
> - &iter);
> - if (err)
> - return err;
> + err = import_ubuf(ITER_SOURCE, ent->payload, ring->max_payload_sz,
> + &iter);
> + if (err)
> + return err;
> + }
>
> fuse_copy_init(&cs, false, &iter);
> cs.is_uring = true;
> @@ -618,10 +623,14 @@ static int fuse_uring_args_to_ring(struct fuse_ring *ring, struct fuse_req *req,
> .commit_id = req->in.h.unique,
> };
>
> - err = import_ubuf(ITER_DEST, ent->payload, ring->max_payload_sz, &iter);
> - if (err) {
> - pr_info_ratelimited("fuse: Import of user buffer failed\n");
> - return err;
> + if (ent->zero_copy) {
> + iter = ent->payload_iter;
> + } else {
> + err = import_ubuf(ITER_DEST, ent->payload, ring->max_payload_sz, &iter);
> + if (err) {
> + pr_info_ratelimited("fuse: Import of user buffer failed\n");
> + return err;
> + }
> }
>
> fuse_copy_init(&cs, true, &iter);
> @@ -1068,6 +1077,17 @@ fuse_uring_create_ring_ent(struct io_uring_cmd *cmd,
> ent->headers = iov[0].iov_base;
> ent->payload = iov[1].iov_base;
>
> + if (READ_ONCE(cmd->sqe->uring_cmd_flags) & IORING_URING_CMD_FIXED) {
> + ent->zero_copy = true;
> + err = io_uring_cmd_import_fixed((u64)ent->payload, payload_size, ITER_DEST,
> + &ent->payload_iter, cmd, 0);
> +
> + if (err) {
> + kfree(ent);
> + return ERR_PTR(err);
> + }
> + }
> +
> atomic_inc(&ring->queue_refs);
> return ent;
> }
> diff --git a/fs/fuse/dev_uring_i.h b/fs/fuse/dev_uring_i.h
> index 51a563922ce1..cb5de6e7a262 100644
> --- a/fs/fuse/dev_uring_i.h
> +++ b/fs/fuse/dev_uring_i.h
> @@ -38,6 +38,10 @@ enum fuse_ring_req_state {
>
> /** A fuse ring entry, part of the ring queue */
> struct fuse_ring_ent {
> + bool zero_copy;
> +
> + struct iov_iter payload_iter;
> +
> /* userspace buffer */
> struct fuse_uring_req_header __user *headers;
> void __user *payload;
> --
> 2.34.1
>
next prev parent reply other threads:[~2025-12-05 0:26 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <CGME20251204083010epcas5p2735e829064ff592b67e88c41fb1e44b3@epcas5p2.samsung.com>
2025-12-04 8:25 ` [PATCH] fuse: add zero-copy to fuse-over-io_uring Xiaobing Li
2025-12-04 22:37 ` kernel test robot
2025-12-05 0:26 ` Joanne Koong [this message]
2025-12-12 16:50 ` kernel test robot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CAJnrk1ZH9wJmdXBKjRnFEPhyocwdX=v=7tsrFjfqN1+FZqRDeQ@mail.gmail.com' \
--to=joannelkoong@gmail.com \
--cc=asml.silence@gmail.com \
--cc=axboe@kernel.dk \
--cc=bschubert@ddn.com \
--cc=dw@davidwei.uk \
--cc=io-uring@vger.kernel.org \
--cc=josef@toxicpanda.com \
--cc=joshi.k@samsung.com \
--cc=kbusch@kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=miklos@szeredi.hu \
--cc=peiwei.li@samsung.com \
--cc=xiaobing.li@samsung.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox