FILESYSTEM IN USERSPACE (FUSE) development
 help / color / mirror / Atom feed
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 6/6] docs: fuse: document io-uring buffer pool and zero-copy uapi
Date: Fri, 14 Aug 2026 11:59:46 -0700	[thread overview]
Message-ID: <20260814185946.3679478-7-joannelkoong@gmail.com> (raw)
In-Reply-To: <20260814185946.3679478-1-joannelkoong@gmail.com>

Add documentation for fuse over io-uring usage of buffer pools and
zero-copy.

Reviewed-by: Bernd Schubert <bernd@bsbernd.com>
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
---
 .../filesystems/fuse/fuse-io-uring.rst        |  36 ++++-
 Documentation/filesystems/fuse/index.rst      |   1 +
 .../fuse/uapi/fuse-uapi-io-uring.rst          | 126 ++++++++++++++++++
 3 files changed, 161 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/filesystems/fuse/uapi/fuse-uapi-io-uring.rst

diff --git a/Documentation/filesystems/fuse/fuse-io-uring.rst b/Documentation/filesystems/fuse/fuse-io-uring.rst
index d73dd0dbd238..29f98057500d 100644
--- a/Documentation/filesystems/fuse/fuse-io-uring.rst
+++ b/Documentation/filesystems/fuse/fuse-io-uring.rst
@@ -11,6 +11,9 @@ and works. For generic details about FUSE see fuse.rst.
 This document also covers the current interface, which is
 still in development and might change.
 
+For the userspace protocol, see
+Documentation/filesystems/fuse/uapi/fuse-uapi-io-uring.rst.
+
 Limitations
 ===========
 As of now not all requests types are supported through io-uring, userspace
@@ -95,5 +98,34 @@ Sending requests with CQEs
  |    <fuse_unlink()                         |
  |  <sys_unlink()                            |
 
-
-
+Buffer pools
+============
+
+Without a buffer pool, every entry needs to pass a dedicated payload buffer
+large enough for the maximum payload size. A buffer pool decouples entries
+from payload buffers. The server hands the kernel one contiguous buffer pool
+of memory and when the kernel sends the server a request, it indicates the
+offset into the pool for that request's payload. Internally, the kernel is
+able to manage/optimize the buffer pool memory however it likes.
+
+A server may also register the pool region with io_uring as a fixed buffer.
+The backing pages are then pinned once, avoiding per-request pinning and
+address translation. This also allows servers to use the same registered
+buffers for subsequent backing store I/O through io-uring, keeping data
+in the same pinned pages without additional pinning / mapping overhead.
+
+Zero-copy
+=========
+
+Zero-copy lets the server read from / write to the client's pages (pinned
+user pages for direct I/O, or page-cache folios for buffered I/O) without an
+intermediary payload copy. This requires CAP_SYS_ADMIN privileges.
+
+When a fuse request arrives for a file that opted into zero-copy, the kernel
+registers the relevant pages (pinned user pages for direct i/o or underlying
+page cache folios for buffered i/o) into a sparse slot in the server's
+io_uring registered buffer table. The server can then operate on these pages
+directly using io-uring fixed buffer operations (eg read_fixed / write_fixed)
+and the kernel unregisters these pages when the request completes.
+Non-page-backed args (eg op out headers) will go through the payload buffer as
+normal.
diff --git a/Documentation/filesystems/fuse/index.rst b/Documentation/filesystems/fuse/index.rst
index 393a845214da..3dada6c4057a 100644
--- a/Documentation/filesystems/fuse/index.rst
+++ b/Documentation/filesystems/fuse/index.rst
@@ -12,3 +12,4 @@ FUSE (Filesystem in Userspace) Technical Documentation
    fuse-io
    fuse-io-uring
    fuse-passthrough
+   uapi/fuse-uapi-io-uring
diff --git a/Documentation/filesystems/fuse/uapi/fuse-uapi-io-uring.rst b/Documentation/filesystems/fuse/uapi/fuse-uapi-io-uring.rst
new file mode 100644
index 000000000000..8367be7ea29d
--- /dev/null
+++ b/Documentation/filesystems/fuse/uapi/fuse-uapi-io-uring.rst
@@ -0,0 +1,126 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=====================================
+FUSE-over-io-uring uapi documentation
+=====================================
+
+Commands
+========
+
+``enum fuse_uring_cmd``:
+
+``FUSE_IO_URING_CMD_ADD_QUEUE``
+  Create a queue identified by ``fuse_uring_cmd_req.qid``. Queue-wide
+  options are passed in ``fuse_uring_cmd_req.flags``:
+
+  ``FUSE_URING_ZERO_COPY``
+    Enable zero-copy on this queue. Requires ``CAP_SYS_ADMIN`` and a buffer
+    pool, which is added separately via ``ADD_BUFPOOL`` before registering
+    entries (see `Zero-copy`_).
+
+``FUSE_IO_URING_CMD_ADD_BUFPOOL``
+  Register the payload buffer pool for an existing queue. The server provides
+  a single contiguous region in ``fuse_uring_cmd_req.bufpool.uaddr`` /
+  ``.len``. This command must be issued after ``ADD_QUEUE`` and before
+  registering any payload-carrying entries on that queue.
+  ``fuse_uring_cmd_req.flags`` must be 0. Submitting this command with
+  ``IORING_URING_CMD_FIXED`` marks the pool as registered, which avoids per
+  i/o pinning/unpinning and mapping overhead (see `Buffer pools`_).
+
+``FUSE_IO_URING_CMD_REGISTER``
+  Register a ring entry (a long-lived SQE that carries the request header
+  iovec). For a zero-copy queue, ``fuse_uring_cmd_req.ent_zero_copy_buf_index``
+  indicates the reserved registered buffer table slot this entry uses for
+  zero-copy (see `Zero-copy`_).
+
+``FUSE_IO_URING_CMD_COMMIT_AND_FETCH``
+  Commit the reply for a completed request and fetch the next one. The
+  request is identified by ``fuse_uring_cmd_req.commit_id`` (the value the
+  kernel reported in ``fuse_uring_ent_in_out.commit_id``).
+
+Structures
+==========
+
+``struct fuse_uring_cmd_req`` (80-byte SQE command area):
+
+============================  ==================================================
+Field                         Meaning
+============================  ==================================================
+``flags``                     Command-specific flags (see each command).
+``commit_id``                 Request id, for ``COMMIT_AND_FETCH``.
+``qid``                       Queue index.
+``bufpool.uaddr``             Pool base address, for ``ADD_BUFPOOL``.
+``bufpool.len``               Pool length in bytes, for ``ADD_BUFPOOL``.
+``bufpool.reserved``          Must be 0, for ``ADD_BUFPOOL``.
+``ent_zero_copy_buf_index``   Per-entry zero-copy slot, for ``REGISTER``.
+============================  ==================================================
+
+``struct fuse_uring_ent_in_out`` (reported by the kernel per request):
+
+============================  ==================================================
+Field                         Meaning
+============================  ==================================================
+``flags``                     ``FUSE_URING_ENT_ZERO_COPY`` if zero-copied.
+``commit_id``                 Id to echo back in ``COMMIT_AND_FETCH``.
+``payload_sz``                Total payload size in bytes (see `Zero-copy`_).
+``offset``                    Payload buffer offset within the pool.
+============================  ==================================================
+
+Buffer pools
+============
+Setup:
+
+* Issue ``ADD_QUEUE`` for the qid.
+* Issue ``ADD_BUFPOOL`` with ``bufpool.uaddr`` and ``bufpool.len`` pointing
+  at the region.
+* Register entries with ``REGISTER``.
+
+For every request that has a payload, the kernel reports where the payload
+lives in ``struct fuse_uring_ent_in_out`` (part of
+``struct fuse_uring_req_header``):
+
+``offset``
+  Byte offset, within the pool region, for this request's payload buffer.
+  The server adds this to the pool base address to locate the payload.
+
+``payload_sz``
+  Number of payload bytes for this request.
+
+To use registered buffers, the server registers the pool region with io_uring
+and submits ``ADD_BUFPOOL`` with ``IORING_URING_CMD_FIXED`` set in
+``sqe->uring_cmd_flags`` and the index of the registered bufpool in
+``sqe->buf_index``. Every SQE the server submits afterwards must follow the
+same fixed-buffer protocol, carrying ``IORING_URING_CMD_FIXED`` and that same
+``sqe->buf_index``. The same registered buffer can be reused for the server's
+backing-store I/O as well (e.g. ``IORING_OP_READ_FIXED`` /
+``IORING_OP_WRITE_FIXED``).
+
+Zero-copy
+=========
+Requirements:
+
+* The server must be privileged (``CAP_SYS_ADMIN``).
+* A zero-copy queue: ``ADD_QUEUE`` with the ``FUSE_URING_ZERO_COPY`` flag set.
+* A buffer pool: ``ADD_BUFPOOL``.
+* For each entry, ``REGISTER`` with ``ent_zero_copy_buf_index`` set to the
+  index this entry uses in the server's io_uring registered-buffer table.
+  This is where the kernel registers the request's pages for the server to
+  access (it is separate from the payload pool). On a non-zero-copy queue this
+  field must be 0.
+
+Zero-copy is selected per open file. The server sets the open-file flag in
+the ``FUSE_OPEN`` / ``FUSE_CREATE`` reply:
+
+``FOPEN_IO_URING_ZERO_COPY``
+  Reads/writes on this open file should use zero-copy.
+
+For a request that is zero-copied, the kernel sets ``FUSE_URING_ENT_ZERO_COPY``
+in ``fuse_uring_ent_in_out.flags`` and places the request's pages at the
+entry's ``ent_zero_copy_buf_index``. The server then issues
+``IORING_OP_READ_FIXED`` / ``IORING_OP_WRITE_FIXED`` against that index to
+transfer the data directly to/from the client's pages.
+
+For such a request, ``payload_sz`` includes the zero-copied page bytes
+(transferred via the registered buffer at ``ent_zero_copy_buf_index``). Any
+non-page-backed args (e.g. op headers) are still copied through the pool
+payload buffer at ``offset``.
-- 
2.52.0


  parent 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 [PATCH v7 0/6] fuse: add io-uring buffer pools and zero-copy Joanne Koong
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 ` Joanne Koong [this message]
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-7-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox