站内 NVMe 协议 已讲清接口与 NVMe-oF 扩展;O_DIRECT 与 io_uring 与 io_uring 系列 覆盖仍走内核的高 IOPS 提交路径。云块 / 新硬件 提到 DPU 与 NVMe-oF 卸载。中间仍缺一层:驱动与块栈搬进用户态之后,一次 I/O 如何经 reactor → NVMe qpair → bdev →(可选)NVMe-oF/vhost,以及相对内核路径各自保证什么、丢掉什么。
本系列回答:用户态轮询存储栈里,延迟与失败落在哪一层,何时不该离开内核块 I/O。
写:
- reactor / poller、绑盘与设备独占。
- 用户态 NVMe 驱动、DMA/mempool、bdev。
- NVMe-oF target / 传输 / initiator、vhost 边界。
- JSON-RPC 生命周期、排障与选型。
不写:Ceph/MinIO 全书、DPDK 网卡教程、未实测 IOPS 排行、完整 virtio 规范。对照内核异步见 io_uring;分布式 RADOS 见 distributed/38(非本系列范围)。
系列状态:01–16 已全部发布(2026-08-13)。 规划见 PLAN.md。无直通 NVMe / RDMA 环境则不粘贴伪造 fio 或 RPC 输出。
版本锚定:SPDK v26.01(LTS;官方文档 / 源码 tag v26.01)。非 LTS 特性(如仅出现在 v26.05+)须显式标注。
适合谁看
- 块存储 / 超融合 / 存储网关数据面工程师,要把「示例跑通」推进到「能归因」。
- 读过 storage/03、storage/79,需要用户态栈坐标的读者。
- 在内核 NVMe、io_uring、SPDK、DPU 卸载之间做路径选型的架构师。
与 storage/03·79 的分工
| 维度 | storage/03 / 79 | 本系列 |
|---|---|---|
| 定位 | 协议演进;内核 Direct+io_uring 组合 | 16 篇用户态栈机制 |
| 深度 | 规范与内核提交路径 | 官方文档路径、源码目录、失败模式、开放问题 |
| 对照 | 略述 NVMe-oF / 用户态可能 | 显式外链 03·79 / io_uring;不重写内核全书 |
读法:只要「本机数据库盘用不用 O_DIRECT+io_uring」→ 79 足够;要「用户态 target 卡在哪、为何 CPU 空转」→ 本系列 01 → 02 → 04 → 06 → 08 → 14。
一、这个领域最值得关注的 5 个问题
- 一次 I/O 的延迟与失败点落在哪一层? → 第 1–7、14 篇。
- 用户态独占设备后,运维与共置付出什么? → 第 3、12、14–16 篇。
- bdev 相对 Linux block 层统一了什么、砍掉了什么? → 第 6–7 篇。
- NVMe-oF 如何把远端命令落到本地 bdev?传输模式差在哪? → 第 8–10 篇。
- 何时选 SPDK 而非内核 NVMe / io_uring? → 第 15–16 篇。
二、篇目依赖关系与推荐阅读路径
flowchart TD
overview["01 Overview"] --> reactor["02 Reactor"]
reactor --> env["03 Env VFIO"]
env --> nvme["04 NVMe Driver"]
nvme --> dma["05 DMA Mempool"]
dma --> bdev["06 bdev Core"]
bdev --> modules["07 bdev Modules"]
modules --> nvmf["08 NVMe-oF Target"]
nvmf --> xport["09 Transport"]
xport --> init["10 Initiator"]
init --> vhost["11 vhost"]
vhost --> rpc["12 JSON-RPC"]
rpc --> obs["13 Observability"]
obs --> trouble["14 Troubleshoot"]
trouble --> vs["15 vs Kernel"]
vs --> select["16 Selection"]
overview --> select
| 路径 | 篇目 | 适合 |
|---|---|---|
| 必读核心 | 1 → 2 → 4 → 6 → 8 → 14 | 快速建立坐标系 |
| 本机用户态盘 | 3 → 4 → 5 → 6 → 7 | 绑盘与 bdev |
| NVMe-oF 深挖 | 8 → 9 → 10 → 14 | 远端块与互通 |
| 对照选型 | 1 → 15 → 16 | 路径选型 |
| 完整通读 | 1 → … → 16 | 系统掌握 |
三、目录与每篇价值点
第一部分:运行时与本地 NVMe(01–06)
- 用户态存储全景
- 相对 03/79/io_uring 的缺口;五条坐标系与 16 篇路线。
- Reactor
与线程模型
- event framework、poller、message passing、I/O 路径无锁边界。
- 环境与绑盘
- hugepage、CPU 亲和、VFIO/UIO、设备独占与回退。
- 用户态 NVMe
驱动
- controller、qpair、poll group;admin vs I/O。
- DMA 与
mempool
- 可 DMA 内存、缓冲池、对齐与零拷贝约束。
- bdev
核心
- 统一块接口、I/O 生命周期、排队与完成。
第二部分:模块、远端与虚拟化(07–12)
- bdev
模块边界
- nvme / aio / malloc / raid / lvol;叠层代价。
- NVMe-oF
target
- subsystem、listener、namespace→bdev。
- 传输层
- RDMA / TCP;轮询 vs 26.01 RDMA interrupt mode。
- Initiator
与互通
- SPDK host 与内核 initiator 对接边界。
- vhost / virtio
边界
- 对 VMM 块后端的位置;非完整 virtio 教程。
- JSON-RPC
与生命周期
- 配置面、热插拔、重启与状态边界。
第三部分:观测、排障与收束(13–16)
- 可观测与性能口径
- iostat / trace;官方 performance report 读法。
- 排障坐标系
- 绑盘、空转、队列满、传输超时、多路径。
- 对照内核路径
- SPDK vs 内核 NVMe vs O_DIRECT+io_uring。
- 选型收束与开放问题
- 排除树;ZNS/KV、DPU、与分布式存储用户态栈关系。
四、延伸阅读
- NVMe 协议与存储接口演进(storage/03)
- O_DIRECT 与 io_uring(storage/79)
- io_uring 系列
- 新硬件对存储的影响(storage/73)
- Zero Copy 的肮脏真相
- 全部系列索引
读完这篇,下一步读什么
优先读同系列或同问题的下一篇,把单篇消费变成主题集群。
【SPDK 用户态存储】用户态存储全景:从 Reactor 到 NVMe-oF 的坐标系
定位 SPDK 相对内核块层、O_DIRECT+io_uring 与 NVMe 协议百科的生态位;钉住 I/O 路径、线程模型、设备独占、块抽象、远端传输五条坐标系,并给出 16 篇阅读路线。
【SPDK 用户态存储】排障坐标系:绑盘、空转、队列满、传输超时与多路径
把 SPDK 常见症状映射到绑盘/环境、reactor CPU、bdev 队列、传输超时、多路径五轴;给出可核对清单与观测入口,不虚构延迟数字与 RPC dump。
【SPDK 用户态存储】bdev 核心:统一块接口、I/O 生命周期与排队完成
把 SPDK bdev 钉成用户态块栈:相对 Linux block 层统一了什么、砍掉了什么;一次 I/O 从提交、多无锁队列排队到完成回调的落点;队列满与 reset 的失败语义。
【SPDK 用户态存储】bdev 模块边界:nvme / aio / malloc 与何时不该叠层
按后端与虚拟层两类划清 SPDK bdev 模块边界:nvme、aio、malloc、null、raid、lvol 各自保证什么;说明叠层何时伤害延迟与排障,并拒绝做成模块百科。