本页目录

ZFS — 不是内核的一部分,但绕不开

覆盖: ZFS 架构 (ZPL/DMU/SPA/ZIL/ARC) → COW 事务模型 → 与 Linux VFS 的集成 (SPL) → 与 Btrfs/bcachefs 的对比 → 许可证问题

为什么 ZFS 不在 Linux 内核中

ZFS 使用 CDDL 许可证,与 Linux 的 GPLv2 不兼容。Sun/Oracle 选择不双许可,导致 ZFS 永远不能合入 Linux 主线。

解决方案⁠: OpenZFS 以 内核模块 的形式提供,通过 DKMS 编译安装。CDDL 模块与 GPL 内核之间的接口通过 SPL (Solaris Porting Layer) 抽象。许可证争议集中在"是否构成衍生作品"——这是一个法律灰色地带,所以各发行版的处理方式不同:

  • Ubuntu: 直接打包了 zfs-dkms
  • Debian: contrib 仓库中提供
  • Fedora/RHEL: 不官方支持(用户自行编译)

ZFS 架构栈

ZFS 架构栈:用户空间到物理设备的调用层次 用户空间 — zfs(1) / zpool(1) / libzfs 内核 (OpenZFS module) ZPL(ZFS POSIX Layer) — VFS 接口(i_op / f_op 等) zfs_znode → 对应 inode → zfs_vnode_ops → VFS file_operations DMU(Data Management Unit) — 事务对象到 block 的映射 dnode→对象(文件/目录/属性) · dmu_tx→事务 · dnode→block pointer tree(间接块) ZIL(ZFS Intent Log) — 同步写 journal zil_commit() → 写入 ZIL 设备(SSD/HDD 分区),加速 fsync(同步写不走大事务) ARC(Adaptive Replacement Cache) — 读缓存 MRU(最近最多使用)+ MFU(最近最频繁使用) · 比 page cache 更先进,可设 zfs_arc_max SPA(Storage Pool Allocator) — 物理设备管理层 metaslab→空闲空间管理 · space map→日志式跟踪 · 分配策略 first-fit / best-fit VDEV(Virtual Device) — RAID / 设备抽象 disk · mirror · raidz(1/2/3) · special(元数据/dedup) · cache(L2ARC) · log(ZIL/SLOG)

COW 事务模型

每个写操作:
  1. 分配一个新块 (在目标 metaslab 中找空闲空间)
  2. 写新数据到分配的块
  3. 更新 dnode 的 block pointer (指向新块, 不指向旧块)
  4. dnode 变了 → dnode 本身也要写新位置 → 更新上层指针
  5. 一路往上 → uberblock (root) 更新 → 原子完成

关键: 所有指针更新都是原子的 (单次写 uberblock)
  → 崩溃后要么看到旧状态, 要么看到新状态 — 没有中间态
  → 这就是"没有 journal"的保证 (COW 自身就是一致性的保证)

事务分组 (TXG):
  ZFS 将多个系统调用的写操作合并为一个事务组 (TXG)
  每 ~5 秒提交一次 (zfs_txg_timeout)
  → 减少碎片, 提高写吞吐
  → fsync 绕过这个延迟: 走 ZIL 独立提交

SLOG 与 ZIL

ZIL (ZFS Intent Log):
  同步写 (O_SYNC / fsync) 的加速器
  正常异步写 → 每 5 秒 TXG → 不需要 ZIL
  同步写 → ZIL 单独记录 → 返回到用户空间 → 快
         → 5 秒后 TXG 提交 → ZIL 记录可丢弃

SLOG (Separate LOG):
  将 ZIL 放在专用设备上 (低延迟 NVMe SSD)
  同步写延迟从 HDD latency 降为 SSD latency
  崩溃恢复: replay ZIL + 最近的 TXG → 完整恢复

ZIL 不是 write cache!
  它只存操作日志 → 数据始终由 TXG 写到主存储
  断电丢失 ZIL → 只丢失最近 5 秒的同步写 (异步写不受影响)

与 Btrfs/bcachefs 的对比

ZFSBtrfsbcachefs
许可证CDDLGPLv2GPLv2
内核集成DKMS modulein-treein-tree (6.7+)
COW始终元数据始终, 数据可选始终
快照ZVOL, dataset 级别subvolumesubvolume
RAIDraidz(1/2/3), mirrorraid0/1/10/5/6多设备分层
ARC/L2ARC无 (用 page cache)
去重在线 (极耗内存)离线 (有工具)
内建压缩lz4, zstd, gzipzstd, lzo, zlibzstd, lz4, gzip
发送/接收zfs send/recvbtrfs send/receive规划中

ZFS 的明显优势是成熟度 (20+ 年生产部署) 和 ARC 读缓存。Btrfs 的优势是内核主线集成和更轻量的 RAID。bcachefs 太新,稳定性待验证。


调试

# ARC 状态 (需要安装 zfs)
cat /proc/spl/kstat/zfs/arcstats

# Pool 状态
zpool status
zpool iostat -v 1

# 当前 TXG
cat /sys/module/zfs/parameters/zfs_txg_timeout

参考与延伸

  • OpenZFS 文档⁠: https://openzfs.github.io/openzfs-docs/
  • 源码⁠: https://github.com/openzfs/zfs
  • 关键论文⁠:
    • "The Zettabyte File System" (Sun, 2003)
    • "The Adaptive Replacement Cache" (Megiddo & Modha, 2003)

关键词: ZFS, DMU, ZIL, ARC, SPA, COW, SLOG, dnode, uberblock, TXG, CDDL, DKMS