Files
zvfs/plan.md
2026-03-02 08:31:01 +00:00

8.6 KiB
Raw Blame History

ZVFS LD_PRELOAD -> RocksDB 加速实施计划(给 Codex 执行)

目标:基于当前 zvfs/zvfs.c + zvfs/zvfs_hook.c,从“单线程 + 接口不全”演进到“可支撑 RocksDB 多线程并有性能收益”。

约束:分阶段、可中断、可重入;每阶段都必须有独立可验证的正确性门槛。


0. 执行规则(必须遵守)

  1. 一次只做一个阶段;阶段内通过验收前不得进入下一阶段。
  2. 每阶段结束后必须更新本文“阶段状态”。
  3. 每阶段保留一个“恢复锚点”:
    • 可编译的代码状态;
    • 一组固定验证命令;
    • 一条阶段 commit建议
  4. 出现阻塞时只回滚当前阶段改动,不回滚已完成阶段。
  5. /zvfs 路径行为必须始终透传到 libc不得回归。

1. 阶段状态(可重入入口)

  • Phase 1: 建立基线与 syscall 覆盖清单RocksDB 实际需求)
  • Phase 2: 修正现有 hook 语义缺口(不改线程模型)
  • Phase 3: 补齐 RocksDB P0 接口集(单线程可跑通)
  • Phase 4: 补齐 RocksDB P1 接口集(目录/锁/截断)
  • Phase 5: 多线程执行模型改造Worker + 请求队列)
  • Phase 6: 并发正确性与崩溃恢复强化
  • Phase 7: 面向 RocksDB 的性能优化与验收

重入方式:中断后先看本区,继续第一个未完成阶段。


2. 当前代码关键问题(来自 zvfs.c/zvfs_hook.c

  1. 单线程瓶颈:所有请求依赖 global_thread + waiter 同步轮询,调用线程直接 spdk_thread_poll,不适合并发。
  2. hook 覆盖不足:当前仅 open/read/write/close/unlink/lseekRocksDB 常用接口大量缺失(如 pread/pwrite/fstat/fsync/fdatasync/ftruncate/rename/openat/fcntl 等)。
  3. 语义缺口:O_TRUNC/O_APPEND/errno 等语义不完整;元数据保存与文件操作一致性较弱。
  4. 线程安全缺口:g_fsfd_tabledirentopen_count 等无锁并发访问。

3. 分阶段计划

Phase 1: 建立基线与 syscall 覆盖清单RocksDB 实际需求)

目标

明确 RocksDB 在当前环境下真实调用了哪些文件接口,得到“必须实现”的优先级列表。

任务

  1. 编译基线:makemake -C test
  2. 跑现有回归:make run-test(普通路径和 /zvfs 路径各一轮)。
  3. strace -fdb_bench(或最小 RocksDB workload导出 syscall 统计。
  4. 产出 docs/rocksdb-syscall-matrix.mdP0/P1/P2 分类 + 是否已支持)。

验收

  • 能给出可复现命令与 syscall 清单。
  • 明确哪些接口是“阻塞 RocksDB 跑通”的 P0。

中断/重入

  • 产物文件存在:docs/rocksdb-syscall-matrix.md
  • 下一次从该清单继续,不需要重跑全量分析。

Phase 2: 修正现有 hook 语义缺口(不改线程模型)

目标

在保持单线程架构不变的前提下,先把已有接口的 POSIX 语义修正到可用状态。

任务

  1. 修复 open 标志位语义:至少覆盖 O_CREAT/O_EXCL/O_TRUNC/O_APPEND
  2. 统一返回值与 errnozvfs_* 失败路径映射到标准 errno。
  3. 修复元数据 I/O 基础问题(如加载/保存边界、错误传播、close 使用 real 函数)。
  4. 增加小型语义回归测试(可放 test/)。

验收

  • 现有 test 全通过。
  • 新增语义测试通过。
  • /zvfs 路径行为无回归。

中断/重入

  • 保留旧逻辑兼容开关(如宏开关)直到本阶段稳定。
  • 提交后可独立回退,不影响后续接口扩展。

Phase 3: 补齐 RocksDB P0 接口集(单线程可跑通)

目标

先实现 RocksDB “必须有才能启动并跑基础 workload” 的接口集合。

P0 接口(优先)

  • 打开类:open64/openat/openat64/__open_2/__open64_2
  • 偏移 I/Opread/pread64/pwrite/pwrite64
  • 元数据:stat/lstat/fstat/fstatat/access
  • 持久化:fsync/fdatasync
  • 变更:rename/renameat/unlinkat

任务

  1. zvfs_hook.c 增加 real 函数指针与统一初始化(建议 pthread_once)。
  2. 所有新 hook 必须支持“路径过滤 + 非 /zvfs 透传”。
  3. 对不支持的语义明确返回 ENOTSUP/EOPNOTSUPP,禁止静默成功。
  4. 增加 pread/pwrite 偏移语义测试。

验收

  • db_bench 单线程基础项可跑:fillseq/fillrandom/readrandom
  • strace 显示 P0 接口已被正确接管或透传。

中断/重入

  • 每新增一类 hook 单独 commitopen/io/meta/sync/rename
  • 中断后按未完成类别继续,不影响已完成类别。

Phase 4: 补齐 RocksDB P1 接口集(目录/锁/截断)

目标

支持 RocksDB 更完整运行路径,尤其是锁文件、目录操作、截断相关语义。

P1 接口

  • ftruncate/truncate
  • fcntl(至少 F_SETLK/F_SETLKW/F_GETLK/F_UNLCK
  • mkdir/rmdir/opendir/readdir/closedir
  • link/symlink/readlink(按 strace 结果决定)

任务

  1. 为目录与锁引入最小可用实现(先保证正确,再优化)。
  2. 对暂不支持特性返回明确 errno不可假成功。
  3. 补充目录/锁语义测试(多进程或多线程最小场景)。

验收

  • db_bench --threads=4 可稳定执行基础 workload。
  • 无明显语义错误锁冲突、目录丢失、truncate 异常)。

中断/重入

  • fcntl 与目录接口分成两个子里程碑。
  • 任一子里程碑完成即可落盘并停在该点。

Phase 5: 多线程执行模型改造Worker + 请求队列)

目标

把当前“调用线程主动 poll”的模式改为“专用 worker poll + 线程安全请求提交”,解决单线程瓶颈。

任务

  1. 新增 zvfs_worker专用线程、请求队列、完成通知cond/futex/eventfd 均可)。
  2. waiter 路径替换为 submit_and_wait 路径;调用线程不再直接 spdk_thread_poll
  3. 增加并发保护:
    • 全局锁:g_fs/mount/fd_table/dirent
    • 文件锁:offset/blob 生命周期
    • 明确锁顺序避免死锁。
  4. 保留回退开关(例如 ZVFS_USE_LEGACY_WAITER)直到压测稳定。

验收

  • 线程数 4/8 下功能测试稳定,无死锁/崩溃。
  • CPU 火焰图或日志能证明调用线程不再承担 SPDK poll。

中断/重入

  • 先实现 worker 生命周期,再迁移 read/write再迁移 open/close。
  • 每迁移一类操作即可独立验证与提交。

Phase 6: 并发正确性与崩溃恢复强化

目标

在多线程基础上补齐一致性:元数据、删除/关闭竞态、异常退出后的可恢复性。

任务

  1. 元数据持久化改为“原子写入流程”(临时文件 + fsync + rename
  2. 修复 unlink/close/open 并发竞态(引用计数与删除时机)。
  3. 建立故障注入测试:kill -9、中途断电模拟(最小可复现脚本)。
  4. 明确恢复策略与错误可观测日志。

验收

  • 故障注入后可重新挂载并读到一致元数据。
  • 并发 open/unlink/close 压测无崩溃无悬挂。

中断/重入

  • 先落地元数据原子写入,再处理并发删除,再做故障注入。

Phase 7: 面向 RocksDB 的性能优化与验收

目标

在正确性稳定后进行性能优化,并给出“确实加速 RocksDB”的证据。

任务

  1. 优化优先级:
    • 对齐写 fast-path 与非对齐 RMW 优化;
    • DMA buffer 复用/池化;
    • 减少全局锁粒度;
    • 批量/延迟元数据刷新策略。
  2. 构建统一 benchmark 脚本:
    • 对照组 A不使用 LD_PRELOAD
    • 对照组 BLD_PRELOAD=./libzvfs.so + /zvfs 路径。
  3. 指标吞吐ops/s、P99 延迟、CPU 使用率、失败率。

验收(最终目标)

  • 在至少一个 RocksDB workload 上达到可重复的性能提升(建议目标 >= 1.3x,最终以实测为准)。
  • 提供完整报告:命令、环境、结果表、结论与剩余瓶颈。

中断/重入

  • 每个优化项必须可单独开关,可单独回滚。

4. 阶段验收矩阵(执行时打勾)

  • P1 已产出 syscall matrix 且可复现。
  • P2 已完成现有语义修复且回归通过。
  • P3 已实现 P0 接口并单线程跑通 RocksDB。
  • P4 已实现 P1 接口并多线程稳定运行。
  • P5 已切换到 worker 并通过并发稳定性测试。
  • P6 已通过崩溃恢复与并发竞态测试。
  • P7 已完成性能对照并证明加速收益。

5. 每阶段固定输出模板(执行时复用)

  1. 改动清单(文件 + 关键点)。
  2. 验证命令与结果。
  3. 风险/已知问题。
  4. 阶段状态勾选更新。
  5. 下一阶段入口条件是否满足。