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()                            |