
PowerFS 通过 NVMe-oF Target 直连架构将 I/O 路径从传统的 4 跳压缩至 2 跳其核心在于彻底移除 Volume Server 这一中间数据节点让客户端通过 SPDK NVMe-oF Initiator 直接与全闪存阵列的 NVMe-oF Target 通信。I/O 路径对比处理环节传统内核栈路径 (4跳)PowerFS Mode A (3跳)PowerFS Mode B (2跳)① 客户端处理客户端 (FUSE/KERNEL)客户端 (FUSE/KERNEL)客户端 (内嵌 SPDK NVMe-oF Initiator)② 中间数据节点Volume Server (用户态处理)Volume Server (SPDK 用户态)无③ 内核文件系统ext4/xfs 等内核文件系统无(SPDK 绕过内核)无④ 介质访问NVMe 驱动 → SSDNVMe SSDNVMe-oF Target → NVMe SSD路径压缩原理传统路径 (4跳)应用 → 客户端 → Volume Server → 内核文件系统 → NVMe驱动 → SSD。PowerFS Mode B (2跳)应用 → 客户端(SPDK Initiator) → NVMe-oF Target → SSD。此架构直接跳过了 Volume Server 和内核文件系统两个环节。架构与实现详解1. 核心架构变更在 NVMe-oF 直连模式 (Mode B) 下PowerFS 的组件职责发生关键变化职责Mode A (自建池) 责任方Mode B (直连阵列) 责任方元数据 (文件名/目录树)Filer RaftFiler Raft (不变)数据物理读写Volume Server SPDK阵列 NVMe-oF Target数据冗余 (RAID/EC)Volume Stripe EC阵列级 RAID/DUAL/EC快照/克隆/重删/压缩需自研阵列原生提供架构上客户端通过NvmeOfBackend直接与阵列通信Filer 仍作为唯一的强一致元数据权威源但返回的StoredFileChunk寻址信息从(volume_id, needle_id)变为直接描述 NVMe namespace 内物理布局的(subsystem_nqn, ns_id, lba, blocks)。2. 关键代码实现客户端内嵌 SPDK NVMe-oF Initiator直接读写阵列的 NVMe namespace// powerfs-volume/src/spdk_nvmeof.rs /// SPDK NVMe-oF Initiator直连全闪阵列的 NVMe namespace pub struct NvmeOfInitiator { controllers: RwLockHashMapSubsystemNqn, NvmeController, ns_map: RwLockHashMapNsHandle, NvmeNsRef, qpairs: ThreadLocalQPair, // per-core 轮询队列 } /// Filer 返回的直连寻址信息 #[derive(Clone, Serialize, Deserialize)] pub struct NvmeOfChunk { pub subsystem: SubsystemNqn, // 阵列 subsystem NQN pub ns_handle: NsHandle, // namespace 逻辑句柄 pub lba: u64, // 起始 LBA pub blocks: u32, // LBA 块数 // ... 其他字段 } impl NvmeOfInitiator { /// 直读 NVMe namespace的 LBA 范围 pub async fn read_chunk(self, chunk: NvmeOfChunk) - ResultVecu8, SpdkError { let ns self.ns_map.read().unwrap() .get(chunk.ns_handle).cloned() .ok_or(SpdkError::NsNotFound(chunk.ns_handle))?; let buf dma_alloc(chunk.blocks as usize * ns.block_size); // SPDK 轮询提交DMA 直接到用户态缓冲区 let qpair self.qpairs.current(); ns.controller.read(ns.nsid, chunk.lba, chunk.blocks, buf, qpair).await?; Ok(buf.to_vec()) } }此实现使得数据面 I/O 完全绕过 Volume Server 和内核协议栈。3. 配置切换通过配置文件即可切换至直连模式无需修改代码# config/fuse-nvmeof.toml [data_backend] mode nvmeof # 切换为 NVMe-oF 直连模式 [nvmeof] subsystems [ { nqn nqn.2026.io.purestorage:flasharray-a, addr 192.168.1.100, port 4420 }, ] transport rdma # 使用 RDMA (RoCEv2/IB) 传输配置指定后客户端将直接与列出的 NVMe-oF Target 建立连接。性能与收益延迟降低以冷读 2MB chunk 为例Mode B 相比传统路径可节省约 0.4ms 的网络与处理延迟全链路延迟降低约 20%。CPU 开销减少单次数据读的 CPU 开销从 Mode A 的约 13μs 降至约 2μs主要节省了 Volume Server 的序列化、反序列化及 Lease 校验开销。带宽提升数据面 CPU 负担转移至阵列控制器客户端采用 SPDK 轮询模式吞吐上限取决于网卡与阵列前端端口能力更易发挥硬件性能。功能与运维简化直接复用阵列原生的快照、克隆、重删、压缩、远程复制等企业级功能运维组件减少无需管理 Volume Server 节点。强一致性保障尽管数据路径改变但强一致语义不变元数据一致性仍由 Filer Raft 集群保证。缓存一致性跨客户端的Callback Invalidation机制原样保留由 Filer 统一协调失效。写互斥原有的 Volume Stripe Lease 可通过两种策略适配1) 委托给阵列端的 NVMe Persistent Reservation2) 在 Filer 层保留薄层 Lease 协调。参考来源全闪存阵列性能发挥不出来PowerFS NVMe-oF Target直连架构跳过中间层释放极致性能全闪存阵列性能发挥不出来PowerFS NVMe-oF Target直连架构跳过中间层释放极致性能