From: Joanne Koong <joannelkoong@gmail.com>
To: miklos@szeredi.hu
Cc: jlayton@kernel.org, libaokun@linux.alibaba.com, axboe@kernel.dk,
bernd@bsbernd.com, amir73il@gmail.com,
fuse-devel@lists.linux.dev
Subject: [PATCH v7 0/6] fuse: add io-uring buffer pools and zero-copy
Date: Fri, 14 Aug 2026 11:59:40 -0700 [thread overview]
Message-ID: <20260814185946.3679478-1-joannelkoong@gmail.com> (raw)
This series implements fuse io-uring buffer pools and zero-copy.
Prior to this series, ents and buffers are tightly coupled where each entry
has its own dedicated payload buffer, requiring N buffers for N entries where
each buffer must be large enough to accomodate the maximum payload size. This
is suboptimal as most request types require vastly less bytes than the maximum
payload size and some requests do not require payload buffers at all.
This series allows servers to pass in a buffer pool (a contiguous chunk of
memory) that the kernel will use as it wishes for servicing ents/requests.
This decoupling reduces the memory usage requirements needed to use
fuse-io-uring and lets the kernel do any optimizations for assigning payload
memory to requests.
This series additionally adds zero copy to fuse io-uring. The server can
directly access client pages or page cache folios without copying data through
an intermediary buffer. This requires CAP_SYS_ADMIN privileges and using
buffer pools. The zero copy patch has a dependency on io-uring registered
bvec changes in [1].
This series is on top of commit 7d87a5a284bb and on top of the io-uring bvec
changes and the changes from the series in [2] applied.
The throughput improvements from registered buffers and zero-copy depends on
how much of the server's per-request latency is spent on data copying vs
backing I/O. When backing I/O dominates, the saved memcpy is a negligible
fraction of overall latency. Please also note that for the server to
read/write into the zero-copied pages, the read/write must go through io-uring
as an IORING_OP_READ_FIXED / IORING_OP_WRITE_FIXED operation.
The throughput improvement from zero-copy depends on how much of the
per-request latency is spent on data copying vs backing I/O. The gain
comes from eliminating the payload-buffer memcpy, but accessing the
zero-copied pages requires the server to issue the read/write as an
IORING_OP_READ/WRITE_FIXED operation. The benefit is largest when the
mempcy is a meaningful fraction of per-request latency while backing i/o
is still noticable enough that the extra io-uring op's overhead doesn't
dominate.
Benchmarked with passthrough_hp (--nopassthrough, q_depth=8) on a
2-socket Intel Xeon Gold 6138 (40 cores / 80 threads), using fio (sync
engine, bs=1M, O_DIRECT, numjobs=2, 30s run + 10s ramp, 3 runs) where
direct-I/O throughput is against a RAM-backed (tmpfs) source (backing
I/O is not the bottleneck):
baseline registered-buf zero-copy (zc vs base)
direct read ~5.1 GB/s ~5.4 GB/s ~8.9 GB/s (+75%)
direct write ~3.4 GB/s ~4.8 GB/s ~5.1 GB/s (+50%)
On a device-bound NVMe (~2 GB/s reads) the read gain shrinks to ~10-16% (no
measurable gains for writes), as backing I/O rather than the eliminated copy
dominates latency. The benefit overall scales with how much of the per-request
latency is the data copy versus backing I/O.
The benchmark script and results can be found in [3]. The libfuse changes can
be found in [4]. To test the server, run:
sudo ~/libfuse/build/example/passthrough_hp ~/src ~/mounts/tmp --nopassthrough
-o io_uring_zero_copy -o io_uring_q_depth=8
Once this series is merged, the libfuse changes will be tidied up and
submitted upstream.
Thanks,
Joanne
[1] https://lore.kernel.org/io-uring/20260612184840.4058966-1-joannelkoong@gmail.com/T/#t
[2] https://lore.kernel.org/fuse-devel/20260715174305.336261-1-joannelkoong@gmail.com/
[3] https://github.com/joannekoong/linux/commits/fuse_zero_copy_benchmarks/
[4] https://github.com/joannekoong/libfuse/commits/zero_copy_v7
Changelog
---------
v6: https://lore.kernel.org/fuse-devel/20260716175908.2339738-1-joannelkoong@gmail.com/
v6 -> v7:
* Use kvmalloc_flex() instead of kmalloc (Bernd)
* Remove registered bufpool flag and add reserved add-bufpool flag, as per
Bernd's preference (Bernd)
v5: https://lore.kernel.org/fuse-devel/20260630211436.2062816-1-joannelkoong@gmail.com/
v5 -> v6:
* Remove WARN_ON tag, add missing barrier (Sashiko)
* Bring back some documentation from v4, rename uapi doc (Amir)
v4: https://lore.kernel.org/fuse-devel/20260612210513.1516038-1-joannelkoong@gmail.com/
v4 -> v5:
* Address Miklos's feedback (separate uring cmd for adding bufpool, pass only
bufpool addr and len, pass back bufpool offset instead of buf id, etc)
* Make zero-copy opt-in on file open
* Do any zeroing for short zero-copy reads instead of accidentally skipping
* that
* Drop Baokun and Jeff's reviewed-bys since the commits had modifications
* Run more rigorous benchmarks, on bare-metal machine
v3: https://lore.kernel.org/fuse-devel/20260522205823.1597313-1-joannelkoong@gmail.com/
v3 -> v4:
* Add reviewed-bys
* Fix documentation typo, add paragraph about aborts to zero-copy commit
message, undo unnecessary padding[6] change, add FUSE_HAS_URING_BUFPOOL
advertisement
v2: https://lore.kernel.org/linux-fsdevel/20260402162840.2989717-1-joannelkoong@gmail.com/
v2 -> v3:
* Rework the uapis to be more ergonomic. Use io-uring registered buffers
infrastructure instead of doing pinning logic in fuse. Get rid of header
pinning as that makes no real perf difference
* Rename from "buffer ring" to buffer pool. Logic is the same, just different
naming
v1: https://lore.kernel.org/linux-fsdevel/20260324224532.3733468-1-joannelkoong@gmail.com/
v1 -> v2:
* Drop kernel managed buffers from io-uring infrastructure and move it to fuse
* Add visual diagrams and more documentatoin to commit messages and
documentation patch
Joanne Koong (6):
fuse: decouple fuse_ring creation from ent registration
fuse: add FUSE_IO_URING_CMD_ADD_QUEUE
fuse: add io-uring buffer pools
fuse: support registered buffer pools in io-uring
fuse: add zero-copy over io-uring
docs: fuse: document io-uring buffer pool and zero-copy uapi
.../filesystems/fuse/fuse-io-uring.rst | 36 +-
Documentation/filesystems/fuse/index.rst | 1 +
.../fuse/uapi/fuse-uapi-io-uring.rst | 126 ++++
fs/fuse/args.h | 2 +
fs/fuse/dev.c | 32 +-
fs/fuse/dev.h | 2 +-
fs/fuse/dev_uring.c | 572 +++++++++++++++---
fs/fuse/dev_uring_i.h | 56 +-
fs/fuse/file.c | 2 +
fs/fuse/fuse_dev_i.h | 2 +
fs/fuse/inode.c | 6 +-
include/uapi/linux/fuse.h | 63 +-
12 files changed, 816 insertions(+), 84 deletions(-)
create mode 100644 Documentation/filesystems/fuse/uapi/fuse-uapi-io-uring.rst
--
2.52.0
next reply other threads:[~2026-08-14 19:00 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-14 18:59 Joanne Koong [this message]
2026-08-14 18:59 ` [PATCH v7 1/6] fuse: decouple fuse_ring creation from ent registration Joanne Koong
2026-08-19 11:34 ` Miklos Szeredi
2026-08-19 11:38 ` Bernd Schubert
2026-08-19 17:56 ` Joanne Koong
2026-08-19 20:05 ` Bernd Schubert
2026-08-19 20:29 ` Joanne Koong
2026-08-19 20:52 ` Bernd Schubert
2026-08-19 21:35 ` Bernd Schubert
2026-08-20 8:02 ` Baokun Li
2026-08-20 16:16 ` Joanne Koong
2026-08-20 17:20 ` Bernd Schubert
2026-08-20 17:46 ` Joanne Koong
2026-08-20 18:27 ` Bernd Schubert
2026-08-21 3:38 ` Baokun Li
2026-08-21 3:24 ` Baokun Li
2026-08-21 3:04 ` Baokun Li
2026-08-14 18:59 ` [PATCH v7 2/6] fuse: add FUSE_IO_URING_CMD_ADD_QUEUE Joanne Koong
2026-08-14 18:59 ` [PATCH v7 3/6] fuse: add io-uring buffer pools Joanne Koong
2026-08-14 18:59 ` [PATCH v7 4/6] fuse: support registered buffer pools in io-uring Joanne Koong
2026-08-17 10:15 ` Bernd Schubert
2026-08-14 18:59 ` [PATCH v7 5/6] fuse: add zero-copy over io-uring Joanne Koong
2026-08-17 13:05 ` Bernd Schubert
2026-08-14 18:59 ` [PATCH v7 6/6] docs: fuse: document io-uring buffer pool and zero-copy uapi Joanne Koong
2026-08-14 19:23 ` [PATCH v7 0/6] fuse: add io-uring buffer pools and zero-copy Joanne Koong
2026-08-17 15:29 ` Miklos Szeredi
2026-08-17 18:23 ` Jens Axboe
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=20260814185946.3679478-1-joannelkoong@gmail.com \
--to=joannelkoong@gmail.com \
--cc=amir73il@gmail.com \
--cc=axboe@kernel.dk \
--cc=bernd@bsbernd.com \
--cc=fuse-devel@lists.linux.dev \
--cc=jlayton@kernel.org \
--cc=libaokun@linux.alibaba.com \
--cc=miklos@szeredi.hu \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.