요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. 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() |
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
설계 범위와 현재 지원 한계
1-20이 문서는 FUSE 커널·사용자 공간 통신을 io_uring으로 구성하는 방법과 기본 동작을 설명합니다. FUSE 자체의 일반 개념은 `fuse.rst`를 참고해야 합니다.
여기서 다루는 interface는 아직 개발 중이므로 변경될 수 있습니다. 구현에 의존하는 사용자 공간 daemon은 고정 ABI라고 가정하지 말고 대상 커널의 interface와 함께 검증해야 합니다.
현재 모든 FUSE request type이 io_uring 경로를 지원하는 것은 아닙니다. io_uring setup을 완료한 뒤에도 사용자 공간은 `/dev/fuse`의 기존 request 경로를 함께 처리해야 합니다.
특히 daemon 쪽에서 시작하는 notification과 interrupt는 io_uring으로 처리되지 않으므로 고전적인 `/dev/fuse` interface가 필수입니다. 따라서 전환은 전체 대체가 아니라 지원 request만 ring queue로 보내는 혼합 동작입니다.
설정 완료 뒤에도 두 경로를 함께 유지해야 합니다.
.. 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.
Queue 등록과 COMMIT_AND_FETCH 순환
21-47io_uring setup이 끝나기 전까지 FUSE kernel request는 기존 `/dev/fuse` read/write interface를 통해 queue됩니다.
FUSE-over-io-uring을 준비하려면 사용자 공간 fuse-server가 `/dev/fuse` connection file descriptor에 `opcode = IORING_OP_URING_CMD`인 SQE를 제출해야 합니다.
최초 제출의 subcommand는 `FUSE_URING_REQ_REGISTER`이며, 이 호출은 kernel에서 사용할 ring entry를 등록하기만 합니다. 원문의 sequence diagram에는 동일한 등록 명령이 `FUSE_URING_CMD_REGISTER`로 표기되어 있으므로 구현 header의 현재 symbol과 함께 확인해야 합니다.
각 queue에 entry가 하나 이상 제출되면 kernel이 request를 ring queue에 넣기 시작합니다. CPU core마다 독립적인 fuse-io-uring queue가 있습니다.
사용자 공간은 CQE에 담긴 FUSE request를 처리한 뒤 결과를 `FUSE_URING_REQ_COMMIT_AND_FETCH` subcommand로 제출합니다. kernel은 현재 request를 완료하고 그 entry를 다시 사용 가능한 상태로 표시합니다.
대기 중인 request가 있으면 방금 반환된 entry로 다음 request를 즉시 daemon에 제출합니다. 따라서 하나의 entry는 등록, request 전달, 결과 commit, 다음 request fetch의 순환 수명을 가집니다.
queue별 entry가 등록된 뒤 반복 사용되는 흐름입니다.
ring 활성화 기준과 다음 동작을 정리합니다.
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()
CQE 기반 unlink 요청의 전체 왕복
48-99초기 SQE sequence에서 FUSE daemon은 `io_uring_submit()`으로 `IORING_OP_URING_CMD`와 register subcommand를 제출합니다. 이어 `io_uring_wait_cqe()` 또는 `io_uring_submit_and_wait()`로 CQE를 기다립니다.
kernel에서는 uring command가 `fuse_uring_cmd()`로 들어와 `fuse_uring_register()`가 entry를 등록합니다. 이 단계는 실제 filesystem operation보다 앞서 ring의 request 운반 자원을 준비합니다.
예시 `rm /mnt/fuse/file`은 `sys_unlink()`에서 `fuse_unlink()`로 들어갑니다. FUSE request를 할당한 뒤 `fuse_send_one()`과 `fuse_uring_queue_fuse_req()`를 거쳐 foreground queue에 넣습니다.
`fuse_uring_add_req_to_ring_ent()`가 사용 가능한 ring entry에 request를 연결하고 `fuse_uring_copy_to_ring()`이 내용을 공유 ring으로 복사합니다. `io_uring_cmd_done()`이 CQE를 완료해 daemon에 전달합니다.
kernel의 unlink 호출은 `request_wait_answer()`에서 `req->waitq`를 기다리며 잠듭니다. 이 대기는 daemon이 결과를 commit해 request를 끝낼 때까지 syscall이 먼저 반환하지 않도록 합니다.
daemon은 CQE를 받아 FUSE request를 처리하고 결과와 다음 request fetch 요청을 `IORING_OP_URING_CMD` 및 `FUSE_URING_CMD_COMMIT_AND_FETCH`로 제출합니다.
kernel은 다시 `fuse_uring_cmd()`에 들어와 `fuse_uring_commit_fetch()`를 실행합니다. `fuse_uring_commit()` 안에서 `fuse_uring_copy_from_ring()`이 결과를 원래 FUSE request로 복사합니다.
`fuse_uring_req_end()`와 `fuse_request_end()`가 request를 끝내고 `req->waitq`를 깨웁니다. 이어 `fuse_uring_next_fuse_req()`가 다음 대기 request를 처리하거나 새 request를 기다립니다.
잠들었던 `fuse_unlink()`가 깨어나 반환하고 마지막으로 `sys_unlink()`가 사용자 공간에 결과를 돌려줍니다. ring entry는 동시에 다음 request를 받을 준비가 되어 CQE 왕복과 syscall 수명이 연결됩니다.
원문의 좌우 ASCII sequence를 시간 순서로 정리했습니다.
request 생성, daemon 처리, wait queue wakeup의 순서를 보존합니다.
| | 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() |
요약·해설
fuse-io-uring.rst:1-99FUSE-over-io-uring은 CPU별 queue에 미리 등록한 entry를 통해 kernel request와 daemon 결과를 CQE·uring command로 왕복시킵니다. `COMMIT_AND_FETCH`는 완료 결과 제출과 같은 entry의 다음 request 수신을 결합해 syscall 대기와 queue 재사용 비용을 줄입니다.
현재 notification과 interrupt는 계속 `/dev/fuse` 경로로 처리해야 하므로 daemon은 두 interface를 동시에 유지해야 합니다. 이 interface는 개발 중이며 register·commit symbol은 사용 중인 kernel header와 대조해야 합니다.
entry 등록에서 syscall 완료까지의 압축된 흐름입니다.