zvfs: fio file

This commit is contained in:
2026-03-02 08:31:01 +00:00
parent f82e089325
commit 321212826b
8 changed files with 704 additions and 778 deletions

View File

@@ -42,8 +42,8 @@ zvfs的测试结果
```shell ```shell
cd /home/lian/share/10.1-spdk/spdk cd /home/lian/share/10.1-spdk/spdk
export LD_LIBRARY_PATH=/home/lian/share/10.1-spdk/spdk/build/lib:/home/lian/share/10.1-spdk/spdk/dpdk/build/lib:$LD_LIBRARY_PATH export LD_LIBRARY_PATH=/home/lian/share/10.1-spdk/zvfs/spdk/build/lib:/home/lian/share/10.1-spdk/zvfs/spdk/dpdk/build/lib:$LD_LIBRARY_PATH
export PATH=/home/lian/share/10.1-spdk/spdk/build/bin:$PATH export PATH=/home/lian/share/10.1-spdk/zvfs/spdk/build/bin:$PATH
./build/bin/spdk_nvme_perf \ ./build/bin/spdk_nvme_perf \
-r 'trtype:PCIe traddr:0000:03:00.0' \ -r 'trtype:PCIe traddr:0000:03:00.0' \
@@ -84,8 +84,6 @@ Total : 80122.94 312.98 399.36 3
-r 'trtype:PCIe traddr:0000:03:00.0' \ -r 'trtype:PCIe traddr:0000:03:00.0' \
-q 1 -o 131072 -w write -t 5 -q 1 -o 131072 -w write -t 5
root@ubuntu:/home/lian/share/10.1-spdk/spdk# export LD_LIBRARY_PATH=/home/lian/share/10.1-spdk/spdk/build/lib:/home/lian/share/10.1-spdk/spdk/dpdk/build/lib:$LD_LIBRARY_PATH
root@ubuntu:/home/lian/share/10.1-spdk/spdk# export PATH=/home/lian/share/10.1-spdk/spdk/build/bin:$PATH
root@ubuntu:/home/lian/share/10.1-spdk/spdk# ./build/bin/spdk_nvme_perf -r 'trtype:PCIe traddr:0000:03:00.0' -q 1 -o 131072 -w write -t 5 root@ubuntu:/home/lian/share/10.1-spdk/spdk# ./build/bin/spdk_nvme_perf -r 'trtype:PCIe traddr:0000:03:00.0' -q 1 -o 131072 -w write -t 5
Initializing NVMe Controllers Initializing NVMe Controllers
Attached to NVMe Controller at 0000:03:00.0 [15ad:07f0] Attached to NVMe Controller at 0000:03:00.0 [15ad:07f0]

9
fio/readme.md Normal file
View File

@@ -0,0 +1,9 @@
```shell
sudo apt install fio
fio sample.fio
LD_PRELOAD=../zvfs/libzvfs.so fio zvfs.fio
```

14
fio/sample.fio Normal file
View File

@@ -0,0 +1,14 @@
[global]
ioengine=sync # 同步 I/O
direct=0 # 使用内核页缓存,测试系统调用性能
bs=128k # 块大小
size=1G # 每个文件大小
numjobs=2 # 并发线程数
runtime=60 # 测试运行时间,秒
time_based=1
rw=randrw # 随机读写
rwmixread=70 # 70% 读30% 写
group_reporting=1 # 汇总报告
[test_syscall]
filename=/tmp/fio_sample_testfile

14
fio/zvfs.fio Normal file
View File

@@ -0,0 +1,14 @@
[global]
ioengine=sync
direct=0
bs=128k
size=1G
numjobs=2
runtime=60
time_based=1
rw=randrw
rwmixread=70
group_reporting=1
[test_hook]
filename=/zvfs/fio_zvfs_testfile

414
plan.md
View File

@@ -1,346 +1,232 @@
# ZVFS -> RocksDB LD_PRELOAD 可重入改造计划(给 Codex 执行) # ZVFS LD_PRELOAD -> RocksDB 加速实施计划(给 Codex 执行)
> 目标:这是一份“可中断、可恢复、可分段提交”的实施计划。 > 目标:基于当前 `zvfs/zvfs.c` + `zvfs/zvfs_hook.c`,从“单线程 + 接口不全”演进到“可支撑 RocksDB 多线程并有性能收益”。
> 原则:每阶段都能独立编译、独立验证、独立回滚,不要求一次性改完。 >
> 约束:**分阶段、可中断、可重入**;每阶段都必须有独立可验证的正确性门槛。
--- ---
## 0. 执行约束(必须遵守) ## 0. 执行规则(必须遵守)
1. **一次只做一个阶段**,每阶段结束后必须通过该阶段验收再进入下一阶段。 1. 一次只做一个阶段;阶段内通过验收前不得进入下一阶段。
2. **不跨阶段混改**:例如阶段 1 不改 hook 覆盖,阶段 3 不重构线程模型 2. 每阶段结束后必须更新本文“阶段状态”
3. **每阶段必须留下恢复锚点** 3. 每阶段保留一个“恢复锚点”
- 文档状态更新(本文件“阶段状态”区) - 可编译的代码状态;
- 代码中保留临时兼容开关(若有) - 一组固定验证命令;
- 能独立提交 commit建议 - 一条阶段 commit建议
4. **失败可回退**:阶段内失败仅回退本阶段改动,不影响已完成阶段。 4. 出现阻塞时只回滚当前阶段改动,不回滚已完成阶段。
5. **默认保持旧行为可用**,新增能力通过新路径启用,逐步替换旧路径 5. `/zvfs` 路径行为必须始终透传到 libc不得回归
--- ---
## 1. 阶段状态(可重入) ## 1. 阶段状态(可重入入口
- [ ] Phase 1: IO 请求结构体落地(单线程兼容模式 - [ ] Phase 1: 建立基线与 syscall 覆盖清单RocksDB 实际需求
- [ ] Phase 2: Worker + 多线程执行模型落地 - [ ] Phase 2: 修正现有 hook 语义缺口(不改线程模型)
- [ ] Phase 3: 偏移型 IO 完整化pread/pwrite 语义 - [ ] Phase 3: 补齐 RocksDB P0 接口集(单线程可跑通
- [ ] Phase 4: RocksDB 核心 hook 补齐P0 - [ ] Phase 4: 补齐 RocksDB P1 接口集(目录/锁/截断
- [ ] Phase 5: 目录/锁/截断接口补齐P1 - [ ] Phase 5: 多线程执行模型改造Worker + 请求队列
- [ ] Phase 6: 元数据一致性与崩溃恢复 - [ ] Phase 6: 并发正确性与崩溃恢复强
- [ ] Phase 7: 性能增强与观测 - [ ] Phase 7: 面向 RocksDB 的性能优化与验收
> 重入方式:中断后先看此状态区 + 对应阶段“完成定义”,从未完成阶段继续 > 重入方式:中断后先看本区,继续第一个未完成阶段。
--- ---
## 2. 基线与分支策略 ## 2. 当前代码关键问题(来自 `zvfs.c`/`zvfs_hook.c`
### 2.1 基线要求 1. 单线程瓶颈:所有请求依赖 `global_thread + waiter` 同步轮询,调用线程直接 `spdk_thread_poll`,不适合并发。
- 当前 `libzvfs.so` 可正常构建 2. hook 覆盖不足:当前 `open/read/write/close/unlink/lseek`RocksDB 常用接口大量缺失(如 `pread/pwrite/fstat/fsync/fdatasync/ftruncate/rename/openat/fcntl` 等)
- 当前 `func_test` 可运行 3. 语义缺口:`O_TRUNC/O_APPEND/errno` 等语义不完整;元数据保存与文件操作一致性较弱
- 已确认 `/zvfs` 路径仍由现有 hook 接管 4. 线程安全缺口:`g_fs``fd_table``dirent``open_count` 等无锁并发访问
### 2.2 分支与提交建议
- 每阶段 1 个分支或 1 个 commit
- `phase1-req-struct`
- `phase2-worker-thread`
- `phase3-offset-io`
- ...
- commit message 模板:
- `phaseX: <what> + <compat mode/DoD>`
--- ---
## 3. 分阶段实施 ## 3. 分阶段计划
## Phase 1: IO 请求结构体落地(不改线程模型 ## Phase 1: 建立基线与 syscall 覆盖清单RocksDB 实际需求
### 目标 ### 目标
先把“每次系统调用复用 file 临时字段”的问题解开;引入可扩展请求对象,为后续多线程做准备。 明确 RocksDB 在当前环境下真实调用了哪些文件接口,得到“必须实现”的优先级列表。
**本阶段仍允许单线程执行路径**(内部可继续使用现有 waiter
### 改动范围 ### 任务
- `zvfs/zvfs.h` 1. 编译基线:`make``make -C test`
- `zvfs/zvfs.c` 2. 跑现有回归:`make run-test`(普通路径和 `/zvfs` 路径各一轮)。
- 尽量不改 `zvfs/zvfs_hook.c` 的接口覆盖面(只做必要适配) 3.`strace -f``db_bench`(或最小 RocksDB workload导出 syscall 统计。
4. 产出 `docs/rocksdb-syscall-matrix.md`P0/P1/P2 分类 + 是否已支持)。
### 任务清单 ### 验收
1. 新增 `zvfs_req_t`(最小字段): - 能给出可复现命令与 syscall 清单。
- `op`, `file`, `buf`, `count`, `offset`, `ret`, `op_errno`, `done` - 明确哪些接口是“阻塞 RocksDB 跑通”的 P0。
- 可选:`need_copy_back`, `actual_io_count`
2. 给现有读写流程加“请求入参”版本:
- 新增 `zvfs_read_req(req)` / `zvfs_write_req(req)` 内部函数
- 旧 API `zvfs_read/zvfs_write` 变成薄包装(构造 req 后调用)
3. 去除对 `file->io_count/write_staging_buf/finished` 的强依赖:
- 保留字段可兼容,但主流程改为优先使用 req 字段
4. 错误返回统一:
- 内部负 errno -> 外部返回值 + errno 映射规则固定
### 完成定义DoD ### 中断/重入
- 编译通过 - 产物文件存在:`docs/rocksdb-syscall-matrix.md`
- 现有 `func_test` 全通过 - 下一次从该清单继续,不需要重跑全量分析
- 无并发改造前提下,行为与旧版一致(回归结果一致)。
### 重入点
- 代码里出现 `zvfs_req_t``zvfs_read/zvfs_write` 已封装请求对象。
- 若中断,优先检查旧路径是否仍可用,再继续替换剩余 call path。
--- ---
## Phase 2: Worker + 多线程执行模型 ## Phase 2: 修正现有 hook 语义缺口(不改线程模型
### 目标 ### 目标
将“调用线程主动 poll SPDK”改为“专用 worker 线程 poll + 请求队列”。 在保持单线程架构不变的前提下,先把已有接口的 POSIX 语义修正到可用状态。
建立线程安全基础,不追求本阶段 hook 覆盖齐全。
### 改动范围 ### 任务
- `zvfs/zvfs.h` 1. 修复 `open` 标志位语义:至少覆盖 `O_CREAT/O_EXCL/O_TRUNC/O_APPEND`
- `zvfs/zvfs.c` 2. 统一返回值与 `errno``zvfs_*` 失败路径映射到标准 errno。
- `zvfs/zvfs_hook.c`(仅初始化、提交流程相关) 3. 修复元数据 I/O 基础问题(如加载/保存边界、错误传播、close 使用 real 函数)。
4. 增加小型语义回归测试(可放 `test/`)。
### 任务清单 ### 验收
1. 新增 `zvfs_worker_t` - 现有 `test` 全通过。
- `pthread_t tid` - 新增语义测试通过。
- 请求队列(先用 mutex + list + cond后续可换 MPSC - `/zvfs` 路径行为无回归。
- `running/stopping` 状态
2. 新增生命周期函数:
- `zvfs_worker_start()`
- `zvfs_worker_stop()`
- 在 mount/init 时启动,在 atexit/unmount 时停止
3. 新增提交流程:
- `zvfs_submit_and_wait(req)`:调用线程阻塞等待完成
- worker 线程执行 SPDK 异步链并回填 req
4. 替换 `waiter()` 主路径:
- 保留 waiter 仅作为 fallback编译开关控制
5. 锁与并发保护(最小闭环):
- 全局状态锁:`g_fs/g_mounted/fd_map`
- 文件级锁:`offset` 更新、close 与 io 竞争
### 完成定义DoD ### 中断/重入
- `db_bench --threads=4` 不崩溃、不死锁(先小规模) - 保留旧逻辑兼容开关(如宏开关)直到本阶段稳定
- 旧单线程 case 仍通过 - 提交后可独立回退,不影响后续接口扩展
- 调用线程不再直接 `spdk_thread_poll`
### 重入点
- worker 生命周期已接管主流程(可在日志中看到 worker 启动/停止)。
- 若中断,优先确保 stop 路径可达,避免进程退出挂死。
--- ---
## Phase 3: 偏移型 IO 完整化pread/pwrite 语义 ## Phase 3: 补齐 RocksDB P0 接口集(单线程可跑通
### 目标 ### 目标
补齐 RocksDB 高频调用语义:`pread/pwrite` 不改文件偏移。 先实现 RocksDB “必须有才能启动并跑基础 workload” 的接口集合。
`read/write` 变成 `pread/pwrite + offset 管理` 的包装。
### 改动范围 ### P0 接口(优先)
- `zvfs/zvfs.h` - 打开类:`open64/openat/openat64/__open_2/__open64_2`
- `zvfs/zvfs.c` - 偏移 I/O`pread/pread64/pwrite/pwrite64`
- `zvfs/zvfs_hook.c` - 元数据:`stat/lstat/fstat/fstatat/access`
- 持久化:`fsync/fdatasync`
- 变更:`rename/renameat/unlinkat`
### 任务清单 ### 任务
1. 新增核心接口: 1. `zvfs_hook.c` 增加 real 函数指针与统一初始化(建议 `pthread_once`)。
- `zvfs_pread(file, buf, count, offset)` 2. 所有新 hook 必须支持“路径过滤 + 非 `/zvfs` 透传”。
- `zvfs_pwrite(file, buf, count, offset)` 3. 对不支持的语义明确返回 `ENOTSUP/EOPNOTSUPP`,禁止静默成功。
2. 改造 read/write 4. 增加 `pread/pwrite` 偏移语义测试。
- `read`:在 file lock 下读取并推进 `current_offset`
- `write`:在 file lock 下决定 offset含 O_APPEND
3. 明确并发语义:
- 同一 fd 并发 pread/pwrite 允许并行(不同 offset
- 同一 fd 的 read/write 偏移操作受 file lock 串行
### 完成定义DoD ### 验收
- `pread/pwrite` 回归用例通过 - `db_bench` 单线程基础项可跑:`fillseq/fillrandom/readrandom`
- 同一 fd 的并发 `pread` 不互相污染 offset - `strace` 显示 P0 接口已被正确接管或透传
### 重入 ### 中断/重入
- hook 层可区分 `read/write``pread/pwrite` 路径 - 每新增一类 hook 单独 commitopen/io/meta/sync/rename
- 中断,先保证 `read/write` 仍有正确 fallback - 中断后按未完成类别继续,不影响已完成类别
--- ---
## Phase 4: RocksDB 核心 hook 补齐P0 ## Phase 4: 补齐 RocksDB P1 接口集(目录/锁/截断
### 目标 ### 目标
先覆盖 RocksDB “能跑起来”最关键接口 支持 RocksDB 更完整运行路径,尤其是锁文件、目录操作、截断相关语义
### 改动范围 ### P1 接口
- `zvfs/zvfs_hook.c` - `ftruncate/truncate`
- 必要时 `zvfs/zvfs.h` 新增声明 - `fcntl`(至少 `F_SETLK/F_SETLKW/F_GETLK/F_UNLCK`
- `mkdir/rmdir/opendir/readdir/closedir`
- `link/symlink/readlink`(按 strace 结果决定)
### 任务清单(按优先级) ### 任务
1. 打开类: 1. 为目录与锁引入最小可用实现(先保证正确,再优化)。
- `open/open64/openat/openat64/__open_2/__open64_2` 2. 对暂不支持特性返回明确 errno不可假成功。
2. IO 类: 3. 补充目录/锁语义测试(多进程或多线程最小场景)。
- `pread/pread64/pwrite/pwrite64`
3. 元数据类:
- `fstat/stat/lstat/fstatat/access`
4. 持久化类:
- `fsync/fdatasync`
5. 文件变更类:
- `rename/renameat/renameat2/unlink/unlinkat`
### 实现要求 ### 验收
- `/zvfs` 路径必须透传 real libc - `db_bench --threads=4` 可稳定执行基础 workload
- 所有失败分支必须设置 errno - 无明显语义错误锁冲突、目录丢失、truncate 异常)
- 统一 dlsym 初始化:`pthread_once`,避免递归。
### 完成定义DoD ### 中断/重入
- RocksDB 基础 workload单线程可跑通 - `fcntl` 与目录接口分成两个子里程碑。
- `fillseq`, `fillrandom`, `readrandom` - 任一子里程碑完成即可落盘并停在该点。
- `strace -f` 观察 `/zvfs` 关键 syscall 已被接管。
### 重入点
- 每新增一组 hook 独立提交,失败时可只回退该组。
--- ---
## Phase 5: 目录/锁/截断接口补齐P1 ## Phase 5: 多线程执行模型改造Worker + 请求队列
### 目标 ### 目标
补齐 RocksDB 稳定运行需要的辅助接口 把当前“调用线程主动 poll”的模式改为“专用 worker poll + 线程安全请求提交”,解决单线程瓶颈
### 改动范围 ### 任务
- `zvfs/zvfs_hook.c` 1. 新增 `zvfs_worker`专用线程、请求队列、完成通知cond/futex/eventfd 均可)。
- `zvfs/zvfs.c`(必要后端支撑) 2.`waiter` 路径替换为 `submit_and_wait` 路径;调用线程不再直接 `spdk_thread_poll`
3. 增加并发保护:
- 全局锁:`g_fs/mount/fd_table/dirent`
- 文件锁:`offset/blob 生命周期`
- 明确锁顺序避免死锁。
4. 保留回退开关(例如 `ZVFS_USE_LEGACY_WAITER`)直到压测稳定。
### 任务清单 ### 验收
1. 截断: - 线程数 4/8 下功能测试稳定,无死锁/崩溃。
- `ftruncate/truncate` - CPU 火焰图或日志能证明调用线程不再承担 SPDK poll。
2. 锁:
- `fcntl` 最少支持 `F_SETLK/F_SETLKW/F_UNLCK/F_GETLK`
3. 目录:
- `mkdir/rmdir/opendir/readdir/closedir`
4. 容量提示(可选但建议):
- `fallocate/posix_fallocate`(不支持时明确 `EOPNOTSUPP`
### 完成定义DoD ### 中断/重入
- RocksDB 多线程基础 workload 可稳定运行(`--threads=4/8` - 先实现 worker 生命周期,再迁移 read/write再迁移 open/close
- LOCK 文件语义满足单进程多线程正确性 - 每迁移一类操作即可独立验证与提交
### 重入点
- `fcntl` 与目录接口可拆成两个子阶段提交。
--- ---
## Phase 6: 元数据一致性与崩溃恢复 ## Phase 6: 并发正确性与崩溃恢复强
### 目标 ### 目标
解决 `zvfs_meta.txt` 全量覆盖、崩溃窗口、恢复不确定问题 在多线程基础上补齐一致性:元数据、删除/关闭竞态、异常退出后的可恢复性
### 改动范围 ### 任务
- `zvfs/zvfs_hook.c`meta load/save 1. 元数据持久化改为“原子写入流程”(临时文件 + fsync + rename
- `zvfs/zvfs.c`(关键操作强制 flush 时机) 2. 修复 `unlink/close/open` 并发竞态(引用计数与删除时机)
- 文档与测试脚本 3. 建立故障注入测试:`kill -9`、中途断电模拟(最小可复现脚本)。
4. 明确恢复策略与错误可观测日志。
### 任务清单 ### 验收
1. 元数据写入策略: - 故障注入后可重新挂载并读到一致元数据。
- 从“每次全量覆盖”改为“批量 + 关键点强制刷盘” - 并发 `open/unlink/close` 压测无崩溃无悬挂。
2. 元数据文件格式增强:
- 增加版本号 + CRC
3. 恢复路径:
- 加载失败时回退到最近完整版本(若实现双文件/快照)
4. 关键操作一致性点:
- `rename/unlink/truncate/fsync` 后策略明确
### 完成定义DoD ### 中断/重入
- 人工崩溃注入后kill -9可重新打开 DB - 先落地元数据原子写入,再处理并发删除,再做故障注入
- 元数据损坏能被检测并报错,不默默产生脏状态。
### 重入点
- 先做“格式版本化 + 校验”,再做“批量策略”。
--- ---
## Phase 7: 性能增强与观测 ## Phase 7: 面向 RocksDB 的性能优化与验收
### 目标 ### 目标
在正确性稳定后提性能,确保收益可量化 在正确性稳定后进行性能优化,并给出“确实加速 RocksDB”的证据
### 改动范围 ### 任务
- `zvfs/zvfs.c` 1. 优化优先级:
- 性能脚本与统计输出 - 对齐写 fast-path 与非对齐 RMW 优化;
- DMA buffer 复用/池化;
- 减少全局锁粒度;
- 批量/延迟元数据刷新策略。
2. 构建统一 benchmark 脚本:
- 对照组 A不使用 `LD_PRELOAD`
- 对照组 B`LD_PRELOAD=./libzvfs.so` + `/zvfs` 路径。
3. 指标吞吐ops/s、P99 延迟、CPU 使用率、失败率。
### 任务清单 ### 验收(最终目标)
1. 请求对象池 / DMA buffer 复用 - 在至少一个 RocksDB workload 上达到可重复的性能提升(建议目标 >= 1.3x,最终以实测为准)。
2. 减少全局锁竞争(热点路径细化锁) - 提供完整报告:命令、环境、结果表、结论与剩余瓶颈。
3. 元数据 debounce 与批量刷盘参数化
4. 增加指标:
- op 次数、失败率、平均/尾延迟、队列深度
### 完成定义DoD ### 中断/重入
- 与旧版本对比,多线程 `db_bench` 吞吐显著提升(目标 >1.5x,按实测调整) - 每个优化项必须可单独开关,可单独回滚
- 无新增数据一致性回归。
### 重入点
- 每个优化项独立开关,可单独启停做 A/B。
--- ---
## 4. 阶段间依赖关系(严格 ## 4. 阶段验收矩阵(执行时打勾
1. 必须先完成 Phase 1 再做 Phase 2 - [ ] P1 已产出 syscall matrix 且可复现
2. 必须先完成 Phase 2 再做 Phase 3/4 - [ ] P2 已完成现有语义修复且回归通过
3. Phase 4核心 hook完成后再做 Phase 5辅助 hook - [ ] P3 已实现 P0 接口并单线程跑通 RocksDB
4. Phase 6/7 必须基于 Phase 5 稳定分支 - [ ] P4 已实现 P1 接口并多线程稳定运行
- [ ] P5 已切换到 worker 并通过并发稳定性测试。
- [ ] P6 已通过崩溃恢复与并发竞态测试。
- [ ] P7 已完成性能对照并证明加速收益。
--- ---
## 5. 验收矩阵(执行时打勾 ## 5. 每阶段固定输出模板(执行时复用
### Phase 1 1. 改动清单(文件 + 关键点)。
- [ ] 编译通过 2. 验证命令与结果。
- [ ] `func_test` 通过 3. 风险/已知问题。
- [ ] 请求对象已接管 read/write 内部主流程 4. 阶段状态勾选更新。
5. 下一阶段入口条件是否满足。
### Phase 2
- [ ] worker 模型接管
- [ ] 多线程 smoke 测试通过
- [ ] 无死锁/退出挂死
### Phase 3
- [ ] `pread/pwrite` 语义正确
- [ ] offset 并发污染问题消失
### Phase 4
- [ ] P0 hook 集合已实现
- [ ] RocksDB 单线程 workload 跑通
### Phase 5
- [ ] P1 hook 集合已实现
- [ ] RocksDB 多线程 workload 稳定
### Phase 6
- [ ] 元数据校验与恢复策略生效
- [ ] 崩溃恢复测试通过
### Phase 7
- [ ] 关键指标可观测
- [ ] 性能目标达成或给出瓶颈结论
---
## 6. 风险与应对(执行版)
1. **接口补齐不完整**
- 应对:每阶段跑 `strace -f`,统计 `/zvfs` 相关未接管 syscall。
2. **并发死锁**
- 应对固定锁顺序debug 模式打印锁获取日志。
3. **行为回归**
- 应对保留兼容开关old path直到该阶段验收通过。
4. **性能退化**
- 应对:优化项独立开关,逐项 A/B不一次性合并。
---
## 7. 给 Codex 的执行模板(每阶段复用)
1. 阅读本阶段“目标/任务/DoD/重入点”
2. 只改本阶段文件与最小依赖
3. 本地编译 + 对应测试
4. 更新“阶段状态”勾选
5. 输出:
- 改了什么
- 测了什么
- 还剩什么
6. 等待用户确认再进入下一阶段

9
rocksdb.md Normal file
View File

@@ -0,0 +1,9 @@
```shell
sudo apt install -y build-essential cmake git \
libgflags-dev libsnappy-dev zlib1g-dev libbz2-dev \
liblz4-dev libzstd-dev librocksdb-dev
```

View File

@@ -9,7 +9,6 @@ include $(SPDK_ROOT_DIR)/mk/spdk.modules.mk
include $(SPDK_ROOT_DIR)/mk/spdk.app_vars.mk include $(SPDK_ROOT_DIR)/mk/spdk.app_vars.mk
LIBZVFS := libzvfs.so LIBZVFS := libzvfs.so
APP := func_test
C_SRCS := zvfs.c zvfs_hook.c C_SRCS := zvfs.c zvfs_hook.c
@@ -22,16 +21,13 @@ LDFLAGS += -shared -rdynamic -Wl,-z,nodelete -Wl,--disable-new-dtags \
SYS_LIBS += -ldl SYS_LIBS += -ldl
all: $(LIBZVFS) $(APP) all: $(LIBZVFS)
@: @:
$(LIBZVFS): $(OBJS) $(SPDK_LIB_FILES) $(ENV_LIBS) $(LIBZVFS): $(OBJS) $(SPDK_LIB_FILES) $(ENV_LIBS)
$(LINK_C) $(LINK_C)
$(APP): func_test.c
$(CC) -o $@ $<
clean: clean:
$(CLEAN_C) $(LIBZVFS) $(APP) $(CLEAN_C) $(LIBZVFS)
include $(SPDK_ROOT_DIR)/mk/spdk.deps.mk include $(SPDK_ROOT_DIR)/mk/spdk.deps.mk

View File

@@ -985,52 +985,52 @@ int zvfs_delete(struct zvfs_file_s *file) {
return ok && file->op_errno == 0; return ok && file->op_errno == 0;
} }
int main(int argc, char *argv[]) { // int main(int argc, char *argv[]) {
if (zvfs_env_setup()) { // if (zvfs_env_setup()) {
return -1; // return -1;
} // }
SPDK_NOTICELOG("zvfs_env_setup success\n"); // SPDK_NOTICELOG("zvfs_env_setup success\n");
SPDK_NOTICELOG("\n\n zvfs mount start \n\n"); // SPDK_NOTICELOG("\n\n zvfs mount start \n\n");
zvfs_t *fs = calloc(1, sizeof(zvfs_t)); // zvfs_t *fs = calloc(1, sizeof(zvfs_t));
zvfs_mount(fs); // zvfs_mount(fs);
SPDK_NOTICELOG("\n\n zvfs open start \n\n"); // SPDK_NOTICELOG("\n\n zvfs open start \n\n");
zvfs_file_t *file = calloc(1, sizeof(zvfs_file_t)); // zvfs_file_t *file = calloc(1, sizeof(zvfs_file_t));
file->fs = fs; // file->fs = fs;
zvfs_dirent_t *dirent = calloc(1, sizeof(zvfs_dirent_t)); // zvfs_dirent_t *dirent = calloc(1, sizeof(zvfs_dirent_t));
file->dirent = dirent; // file->dirent = dirent;
zvfs_create(file); // zvfs_create(file);
SPDK_NOTICELOG("\n\n zvfs write start \n\n"); // SPDK_NOTICELOG("\n\n zvfs write start \n\n");
char *buffer = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // char *buffer = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
zvfs_write(file, buffer, strlen(buffer)); // zvfs_write(file, buffer, strlen(buffer));
char *buffer2 = "abcdefghijklmnopqrstuvwxyz"; // char *buffer2 = "abcdefghijklmnopqrstuvwxyz";
zvfs_write(file, buffer2, strlen(buffer2)); // zvfs_write(file, buffer2, strlen(buffer2));
SPDK_NOTICELOG("\n\n zvfs read start \n\n"); // SPDK_NOTICELOG("\n\n zvfs read start \n\n");
file->current_offset = 0; // file->current_offset = 0;
char rbuffer[BUFFER_SIZE] = {0}; // char rbuffer[BUFFER_SIZE] = {0};
int n = zvfs_read(file, rbuffer, BUFFER_SIZE); // int n = zvfs_read(file, rbuffer, BUFFER_SIZE);
SPDK_NOTICELOG("READ BUFFER:%d, %s\n", n, rbuffer); // SPDK_NOTICELOG("READ BUFFER:%d, %s\n", n, rbuffer);
SPDK_NOTICELOG("\n\n zvfs close start \n\n"); // SPDK_NOTICELOG("\n\n zvfs close start \n\n");
zvfs_close(file); // zvfs_close(file);
SPDK_NOTICELOG("\n\n zvfs delete start \n\n"); // SPDK_NOTICELOG("\n\n zvfs delete start \n\n");
zvfs_delete(file); // zvfs_delete(file);
free(dirent); // free(dirent);
free(file); // free(file);
SPDK_NOTICELOG("\n\n zvfs umount start \n\n"); // SPDK_NOTICELOG("\n\n zvfs umount start \n\n");
zvfs_umount(fs); // zvfs_umount(fs);
free(fs); // free(fs);
} // }