本页目录

文件系统实现

覆盖: ext4 (extent tree/jbd2/delayed allocation) → XFS (AG/B+tree/reflink) → Btrfs (COW/subvolume/snapshot/checksum) → bcachefs (6.7+) 内核版本: 2.6 ~ 6.x

概述

Linux 支持的本地文件系统各有不同的设计哲学:

  • ext4: 稳定性优先,journal + delayed allocation,适合通用场景
  • XFS: 大规模并行 IO,分配组 (AG) 设计,适合大文件和高并发
  • Btrfs: COW + checksum + snapshot,适合 NAS 和需要数据完整性保障的场景
  • bcachefs: 新生代 COW 文件系统 (6.7+),copygc + multiple devices + compression

ext4: 稳定的通用方案

Extent Tree

// ext4 使用 extent tree 替代间接块 (ext2/3 的间接/双间接/三间接)
// 一个 extent 描述: "文件偏移 X ~ X+LEN 映射到磁盘块 Y ~ Y+LEN"

struct ext4_extent {
    __le32  ee_block;       // 逻辑块号 (文件内偏移)
    __le16  ee_len;         // 此 extent 覆盖的块数
    __le16  ee_start_hi;    // 物理块号高 16 位
    __le32  ee_start_lo;    // 物理块号低 32 位 (48-bit 块号)
};

// extent tree 是一棵 B-tree (在 inode 内或额外的块中)
// ext4_inode->i_data[60] = 4 个 ext4_extent + 1 个 header
//   → 前 4 个 extent 直接存在于 inode 中 (无需额外的块读取!)
//   → 超过 4 个 → 分裂为 B-tree 节点

// 为什么比间接块更好?
//   间接块: N 个块 → O(N) 查找 (每个块一个指针)
//   extent:  N 个块 → O(1) extent 覆盖 (连续块用一条记录)
//   碎片化文件: extent tree 可能会有多个节点 → 仍是 O(log N)

jbd2: Journal

// 写操作在 ext4 中的路径:
//   1. 写数据到磁盘 (data)
//   2. 写元数据变更到 journal (metadata)
//   3. 标记 journal commit 完成
//   4. checkpoint: 将 journal 中的元数据写回实际位置
//
// mount 时:
//   检查 journal → replay 已 commit 但未 checkpoint 的事务
//   → 恢复一致性 (fsck 很少需要)

// data=ordered (默认):
//   先写数据 → 再写 journal → 数据不会在元数据之前可见
//   → 崩溃后文件数据完整 (元数据可能不完整但不会指向垃圾)

// data=writeback:
//   数据可以乱序 → 更快, 但崩溃后可能看到旧数据

Delayed Allocation

ext4 延迟分配:
  写操作 → 先在 page cache 中积累 → 不立即分配磁盘块
  → writeback 时 (积累了几秒) → 分配大段连续 extent
  → 减少碎片, 提高顺序写性能

代价:
  1. write() 返回成功不代表磁盘空间已分配 → ENOSPC 延迟到回写
  2. 崩溃时丢失更多数据 (page cache 中的脏页, 还没分配磁盘块)

fallocate 可以预先分配空间, 避免 ENOSPC 延迟

XFS: 大规模并行

分配组 (Allocation Group)

XFS 将文件系统切分为多个 AG (Administrative Group)
每个 AG 独立管理自己的 inode 和空闲空间 B+tree
  → 多线程可以并行分配 → 避免全局锁
  → 高并发场景 (如多路数据库) 优于 ext4

AGs: [AG 0] [AG 1] [AG 2] ... [AG N]
  每个 AG: 有自己的 superblock 副本, inode B+tree, free space B+tree

B+tree 元数据

// XFS 几乎所有的元数据都组织为 B+tree:
//   inode B+tree:    inode number → inode 数据
//   free space B+tree: offset → 空闲 extent
//   extent B+tree:     file offset → disk extent (per-inode)
//
// B+tree 的通用实现: fs/xfs/libxfs/xfs_btree.c
XFS 5.x+ 支持 reflink (共享数据块, COW):
  cp --reflink=always a b
    → a 和 b 共享相同的数据 extent
    → 任一方修改 → COW → 复制被修改的块 → 各自独立

与 Btrfs 的区别:
  XFS reflink 是 extent 级 COW — 不复制整个文件
  Btrfs 是文件级 COW — 每个快照/子卷独立写

Btrfs: COW 与数据完整性

COW 架构

Btrfs 的 COW:
  所有写操作都写新位置 → 不覆盖旧数据
  1. 分配新的 extent 到空闲空间
  2. 写入新数据
  3. 更新元数据 B-tree 指向新 extent
  4. 旧 extent 变为空闲

  崩溃安全性:
    因为是 COW → 旧数据总是在原地
    → 不需要 journal (快照和 reflink 天然支持)
    → transaction commit = 写 superblock 新根

  代价:
    碎片化 (频繁 COW → 逻辑连续的数据物理上散布)
    写放大 (小修改 → 整个 extent 复制)

核心特性

Snapshots (快照):
  btrfs subvolume snapshot . snapshots/$(date +%Y%m%d)
    → O(1) 创建, 不复制数据
    → COW 保证: 修改原始子卷不影响快照

Subvolumes (子卷):
  独立的命名空间, 可以单独挂载
  类 ZFS 的 dataset 概念

Checksum (校验和):
  每个数据块和元数据块都有 checksum (crc32c)
  读时自动校验 → 检测 bit rot / 静默损坏
  与 RAID1 profile 配合: 检测到损坏 → 从镜像自动修复

Compression:
  mount -o compress=zstd → 按 extent 压缩 (zlib/lzo/zstd)

B-tree 森林

Btrfs 的元数据组织:
  多种 B-tree (共享 B-tree 代码):
    Root tree    → 指向其他树的根
    FS tree      → 文件/目录的 inode (每个子卷一个)
    Extent tree  → extent 分配情况
    Chunk tree   → 块组到物理块的映射
    Device tree  → 设备信息
    Csum tree    → extent checksum

bcachefs: 新生代 (6.7+)

设计目标: "btrfs 的功能 + ext4/xfs 的性能 + ZFS 的数据可靠性"
作者: Kent Overstreet (bcache 的原作者)

核心特性:
  - COW 为主, 可选 journal
  - 多设备: 不同磁盘可以承担不同角色
    (SSD 做前台/缓存, HDD 做冷数据存储)
  - 内建压缩 (zstd/lz4/gzip) + checksum
  - 内建加密 (per-extent)
  - 子卷 / snapshot
  - 磁盘格式稳定 (已合入 mainline 6.7)

与 Btrfs 的区别:
  bcachefs 从设计之初就考虑多设备分层
  Btrfs 的 RAID 配置文件系统层面, bcachefs 更灵活

文件系统选择

特性ext4XFSBtrfsbcachefs
最大卷1EB8EB16EB8EB
最大文件16TB8EB16EB8EB
COWreflink only
快照
内建压缩
内建 RAID
校验和journal onlyjournal onlymetadata+datametadata+data
适合场景通用大文件/数据库NAS实验/多设备

参考与延伸

  • 内核文档⁠: Documentation/filesystems/ext4/, Documentation/filesystems/xfs/, Documentation/filesystems/btrfs.rst
  • LWN:
    • "bcachefs merged" (lwn.net/Articles/947587/)
    • "Btrfs: design and implementation" 系列
  • 源码⁠: fs/ext4/, fs/xfs/, fs/btrfs/, fs/bcachefs/

关键词: ext4, extent tree, jbd2, delayed allocation, XFS, allocation group, B+tree, Btrfs, COW, checksum, bcachefs