5. FUSE-over-io-uring uapi documentation

5.1. 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).

5.2. 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.

5.3. 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).

5.4. 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.