FUSE-over-io-uring 设计文档¶
本文档涵盖了 FUSE 内核/用户空间通过 io-uring 进行通信的配置和工作原理。有关 FUSE 的通用详细信息,请参阅FUSE。
本文档还涵盖了当前仍在开发中且可能更改的接口。
限制¶
截至目前,并非所有请求类型都通过 io-uring 支持,用户空间在 io-uring 设置完成后仍需通过 /dev/fuse 处理请求。特别是通知(由守护进程发起)和中断。
Fuse io-uring 配置¶
Fuse 内核请求通过经典的 /dev/fuse 读/写接口排队——直到 io-uring 设置完成。
为了设置 fuse-over-io-uring,fuse-server(用户空间)需要向 /dev/fuse 连接文件描述符提交 SQE(操作码 = IORING_OP_URING_CMD)。首次提交使用子命令 FUSE_URING_REQ_REGISTER,这将只是注册条目以使其在内核中可用。
一旦每个队列至少提交一个条目,内核就开始向环形队列入队。请注意,每个 CPU 核心都有自己的 fuse-io-uring 队列。用户空间处理 CQE/fuse 请求,并将结果作为子命令 FUSE_URING_REQ_COMMIT_AND_FETCH 提交——内核完成请求并再次标记条目可用。如果有挂起的请求等待,该请求将立即再次提交给守护进程。
初始 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() |
使用 CQE 发送请求 --------------------------
| | 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() |