mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-09-18 23:19:34 +02:00
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> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
127 lines
5.4 KiB
ReStructuredText
127 lines
5.4 KiB
ReStructuredText
.. 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``.
|