---
title: 文件系统实现
url: https://doc.liz6.com/linux-kernel/03-file-system/03-filesystem-implementation
locale: zh
area: linux-kernel
tags:
- linux-kernel
- 文件系统
date: 2026-06-30
modified: 2026-06-30
description: '覆盖: ext4 (extent tree/jbd2/delayed allocation) → XFS (AG/B+tree/reflink) → Btrfs (COW/subvolume/snapshot/checksum) → bcachefs (6.7+) 内核版本: 2.6 ~ 6.x'
---

# 文件系统实现

> 覆盖: 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

```c
// 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

```c
// 写操作在 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 元数据

```c
// 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
```

### Reflink 与 COW

```
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 更灵活
```

---

## 文件系统选择

| 特性 | ext4 | XFS | Btrfs | bcachefs |
|------|------|-----|-------|----------|
| 最大卷 | 1EB | 8EB | 16EB | 8EB |
| 最大文件 | 16TB | 8EB | 16EB | 8EB |
| COW | 否 | reflink only | 是 | 是 |
| 快照 | 否 | 否 | 是 | 是 |
| 内建压缩 | 否 | 否 | 是 | 是 |
| 内建 RAID | 否 | 否 | 是 | 是 |
| 校验和 | journal only | journal only | metadata+data | metadata+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*
