linux/fs/fuse
Joanne Koong b45aaabc62 fuse: add io-uring buffer pools
Right now, ents and buffers are tightly coupled in fuse io-uring 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 (lookup,
open, release, getattr, etc) require vastly less bytes than the maximum
payload size and some requests (unlink, rmdir, fsync, flush, etc) do not
require payload buffers at all.

Instead of requiring a 1:1 coupling between ents and payload buffers,
allow the server to pass in a buffer pool (a contiguous chunk of memory)
that the kernel will use as it wishes for servicing ents/requests.
Entries only reserve a "buffer" from the pool while actively processing
a request that requires a payload buffer. This decoupling and letting
the kernel delegate memory from the pool for requests allows the kernel to
optimize memory usage and reduces the memory usage requirements needed
to use fuse-over-io-uring.

A pool is registered per queue with the new
FUSE_IO_URING_CMD_ADD_BUFPOOL command. The server passes the pool's base
address and length in fuse_uring_cmd_req.bufpool.{uaddr,len}.

Internally, the kernel splits the region into buffers of
ring->max_payload_sz bytes each (nr_bufs = pool len / max_payload_sz). A
queue commits to a payload mode on first use: registering an entry that
carries its own payload selects the legacy per-entry mode, while
ADD_BUFPOOL selects pool mode. The two are mutually exclusive, so
ADD_BUFPOOL must be issued before any payload-carrying entries are
registered on that queue. The queue must have been created before the
bufpool is added, through the FUSE_IO_URING_CMD_ADD_QUEUE command.

The kernel tracks free buffers with a bitmap (a set bit marks a free
buffer). On dispatch, a request that needs a payload claims a free
buffer (find_first_bit + clear). A request that needs none claims
nothing. The buffer's byte offset within the pool is reported to the
server in the new fuse_uring_ent_in_out.offset field so that the server
can locate the payload. On completion the buffer is returned to the pool
or reused directly if the next request on that entry also has a payload.

The FUSE_HAS_IO_URING_BUFPOOL flag advertises kernel support to the
server for bufpools.

Buffer pool request flow
~~~~~~~~~~~~~~~~~~~~~~~~
|  Kernel                                  |  FUSE daemon
|                                          |
|  [request arrives]                       |
|    [claim a free pool buffer]            |
|    >fuse_uring_select_buffer()           |
|    [copy headers to ring]                |
|    [copy payload to buffer]              |
|    [report buffer offset in ent_in_out]  |
|    >io_uring_cmd_done()                  |
|                                          |  [read headers]
|                                          |  [read/write payload at offset]
|                                          |  [process request]
|                                          |  >io_uring_submit()
|                                          |   COMMIT_AND_FETCH
|  >fuse_uring_commit_fetch()              |
|    [copy reply from ring]                |
|    [return buffer to the pool]           |
|    >fuse_uring_recycle_buffer()          |

Reviewed-by: Bernd Schubert <bernd@bsbernd.com>
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
History 2026-08-17 17:02:37 +02:00
..
acl.c fuse: Add SPDX ID lines to some files 2026-06-15 14:06:19 +02:00
args.h fuse: remove fm arg of args->end callback 2026-06-15 14:06:17 +02:00
backing.c fuse: use current creds for backing files 2026-06-15 14:06:19 +02:00
control.c fuse: Add SPDX ID lines to some files 2026-06-15 14:06:19 +02:00
cuse.c fuse: use release/acquire for fch->initialized 2026-07-17 13:06:35 +02:00
dax.c fuse: dax: Move long delayed work on system_dfl_long_wq 2026-06-15 14:06:19 +02:00
dev.c fuse: decouple fuse_ring creation from ent registration 2026-08-17 17:02:37 +02:00
dev.h fuse: decouple fuse_ring creation from ent registration 2026-08-17 17:02:37 +02:00
dev_uring.c fuse: add io-uring buffer pools 2026-08-17 17:02:37 +02:00
dev_uring_i.h fuse: add io-uring buffer pools 2026-08-17 17:02:37 +02:00
dir.c fuse: move "epoch" from dentry.d_time to fuse_dentry.epoch 2026-07-06 15:44:58 +02:00
file.c fuse: use iomap helper to mark folio uptodate 2026-07-08 11:12:48 +02:00
fuse_dev_i.h fuse: fuse_dev_i.h: clean up kernel-doc warnings 2026-06-15 14:06:18 +02:00
fuse_i.h fuse: move "epoch" from dentry.d_time to fuse_dentry.epoch 2026-07-06 15:44:58 +02:00
fuse_trace.h fuse: add fuse_request_sent tracepoint 2026-06-15 14:06:19 +02:00
inode.c fuse: add io-uring buffer pools 2026-08-17 17:02:37 +02:00
ioctl.c fuse: replace __get_free_page() with kmalloc() 2026-05-27 15:12:24 +02:00
iomode.c fuse: remove unused 'inode' parameter in fuse_passthrough_open 2025-08-27 14:29:44 +02:00
Kconfig fuse: fix references to fuse.rst -> fuse/fuse.rst 2025-09-02 11:14:15 +02:00
Makefile fuse: create notify.c 2026-06-15 14:06:17 +02:00
notify.c fuse: use iomap helper to mark folio uptodate 2026-07-08 11:12:48 +02:00
passthrough.c lsm: add backing_file LSM hooks 2026-04-03 16:53:50 -04:00
poll.c fuse: create poll.c 2026-06-15 14:06:17 +02:00
readdir.c fuse: move "epoch" from dentry.d_time to fuse_dentry.epoch 2026-07-06 15:44:58 +02:00
req.c fuse: split out filesystem part of request sending 2026-06-15 14:06:17 +02:00
req_timeout.c fuse: abort related layering cleanup 2026-06-15 14:06:17 +02:00
sysctl.c fuse: move request timeout code to a new source file 2026-06-15 14:06:15 +02:00
sysctl.h fuse: move request timeout code to a new source file 2026-06-15 14:06:15 +02:00
trace.c fuse: move CREATE_TRACE_POINTS to a separate file 2025-09-25 16:22:18 +02:00
virtio_fs.c virtio-fs: avoid double-free on failed queue setup 2026-06-15 14:06:20 +02:00
xattr.c fuse: Add SPDX ID lines to some files 2026-06-15 14:06:19 +02:00