| .. SPDX-License-Identifier: GPL-2.0 |
| |
| ======================================= |
| FUSE-over-io-uring design documentation |
| ======================================= |
| |
| This documentation covers basic details how the fuse |
| kernel/userspace communication through io-uring is configured |
| 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. |
| |
| Limitations |
| =========== |
| As of now not all requests types are supported through io-uring, userspace |
| is required to also handle requests through /dev/fuse after io-uring setup |
| is complete. Specifically notifications (initiated from the daemon side) |
| and interrupts. |
| |
| Fuse io-uring configuration |
| =========================== |
| |
| Fuse kernel requests are queued through the classical /dev/fuse |
| read/write interface - until io-uring setup is complete. |
| |
| In order to set up fuse-over-io-uring fuse-server (user-space) |
| needs to submit SQEs (opcode = IORING_OP_URING_CMD) to the /dev/fuse |
| connection file descriptor. Initial submit is with the sub command |
| FUSE_URING_REQ_REGISTER, which will just register entries to be |
| available in the kernel. |
| |
| Once at least one entry per queue is submitted, kernel starts |
| to enqueue to ring queues. |
| Note, every CPU core has its own fuse-io-uring queue. |
| Userspace handles the CQE/fuse-request and submits the result as |
| subcommand FUSE_URING_REQ_COMMIT_AND_FETCH - kernel completes |
| the requests and also marks the entry available again. If there are |
| pending requests waiting the request will be immediately submitted |
| to the daemon again. |
| |
| Initial SQE |
| -----------:: |
| |
| | | FUSE filesystem daemon |
| | | |
| | | >io_uring_submit() |
| | | IORING_OP_URING_CMD / |
| | | FUSE_URING_CMD_REGISTER |
| | | [wait cqe] |
| | | >io_uring_wait_cqe() or |
| | | >io_uring_submit_and_wait() |
| | | |
| | >fuse_uring_cmd() | |
| | >fuse_uring_register() | |
| |
| |
| Sending requests with CQEs |
| --------------------------:: |
| |
| | | FUSE filesystem daemon |
| | | [waiting for CQEs] |
| | "rm /mnt/fuse/file" | |
| | | |
| | >sys_unlink() | |
| | >fuse_unlink() | |
| | [allocate request] | |
| | >fuse_send_one() | |
| | ... | |
| | >fuse_uring_queue_fuse_req | |
| | [queue request on fg queue] | |
| | >fuse_uring_add_req_to_ring_ent() | |
| | ... | |
| | >fuse_uring_copy_to_ring() | |
| | >io_uring_cmd_done() | |
| | >request_wait_answer() | |
| | [sleep on req->waitq] | |
| | | [receives and handles CQE] |
| | | [submit result and fetch next] |
| | | >io_uring_submit() |
| | | IORING_OP_URING_CMD/ |
| | | FUSE_URING_CMD_COMMIT_AND_FETCH |
| | >fuse_uring_cmd() | |
| | >fuse_uring_commit_fetch() | |
| | >fuse_uring_commit() | |
| | >fuse_uring_copy_from_ring() | |
| | [ copy the result to the fuse req] | |
| | >fuse_uring_req_end() | |
| | >fuse_request_end() | |
| | [wake up req->waitq] | |
| | >fuse_uring_next_fuse_req | |
| | [wait or handle next req] | |
| | | |
| | [req->waitq woken up] | |
| | <fuse_unlink() | |
| | <sys_unlink() | |
| |
| |
| |