Skip to the content.

XFS 与 ext4 的 journal 设计对比

核心区别是:ext4 的传统 JBD2 journal 以 metadata block 为中心;XFS 的 log 以 metadata object 及其修改为中心,并围绕它设计了 transaction aggregation、rolling transaction 和 recovery 机制。

两者都采用 write-ahead logging(WAL):相关 log record 必须先持久化,修改后的 metadata 才能写回 home location,即 metadata 在文件系统中的最终存储位置。

本文主要比较 ext4 的传统 full commit 路径与 XFS delayed logging;ext4 fast commit 单独说明。

设计概览

维度 ext4 / JBD2 XFS
日志层 通用 JBD2,围绕 buffer_head / journal_head 管理 journal 状态 专用 log,通过不同类型的 log item 对接 metadata
记录内容 通常记录修改后的完整 metadata block inode 等使用对象专用格式,buffer 记录 dirty region,另有 intent/done item
Transaction 组织 多个操作的 handle 加入同一个 running transaction 操作使用自己的 xfs_trans,commit 后在 CIL 中聚合
批量提交 commit 一个聚合了多个操作的 JBD2 transaction push 一个聚合了多个 transaction 修改的 CIL checkpoint
Log space 回收 主要通过 transaction 的 checkpoint 状态推进 journal tail 通过 AIL 跟踪仍需 log 保护的 item,推进 log tail
File data 支持 data=ordered、data=writeback、data=journal 只记录 metadata,没有对应的 data=journal 模式

这里的 buffer 指承载 metadata block 内容的内存 buffer。JBD2 使用 buffer_head,并通过关联的 journal_head 管理其 journal 状态;XFS 则使用自己的 xfs_buf 等结构。

1. Log record 的粒度不同

假设只修改一个 inode 的部分字段:

因此,XFS 混合使用 object-specific logging、physical region logging 和 intent logging,不能简单归类为“只记录操作”的 logical journal。它记录的也不一定是精确到单个字段的最小 delta。

这种设计能减少某些 metadata 修改的 log volume,但实际收益取决于修改范围、aggregation 效果以及 workload,不能直接推导出 XFS 在所有场景下都更快。

2. 两者都会合并修改,但 aggregation 的位置不同

ext4 / JBD2

多个操作的 handle
    → 同一个 running transaction
    → 关闭该 transaction 的新 handle 入口,等待已有 handle 结束
    → 写 journal block 和 commit record
    → checkpoint:metadata 写回 home location
    → 回收 journal space

handle 表示一个操作在 JBD2 中的更新上下文,不等于一个独立的 on-disk transaction。多个操作可以共享一个 transaction。

JBD2 可以让新的 running transaction 与旧的 committing transaction 重叠执行;它并不要求每次 commit 都阻塞整个文件系统中的所有新操作。共享 metadata buffer 等依赖仍可能引入等待。

XFS

多个独立的 xfs_trans
    → xfs_trans_commit():将修改合并进 CIL
    → CIL push:写 log record 和 commit record
    → AIL 跟踪仍需 log 保护的 item
    → metadata writeback 等工作使 log tail 向前移动

CIL 是 Committed Item List。这里的 committed 首先表示 transaction 已在内存中完成 commit,并不表示 log 已经持久化。

同一个 object 在一个 CIL checkpoint 内被反复修改,可以合并为包含累计修改的最新 log item 内容,避免每次 xfs_trans_commit() 都生成一份独立的 on-disk log record。

但不能据此认为“ext4 修改十次就写十次 journal”:JBD2 在同一个 transaction 内也会合并同一 block 的多次修改。

XFS 的多个 xfs_trans 也不意味着每个 transaction 都拥有独立的持久化路径;它们最终仍通过共享的 log,并遵守 commit ordering。

两套代码中的 checkpoint 含义不同

读代码时不能将这两个 checkpoint 当成同一个阶段。

3. XFS 用 rolling transaction 与 intent 支持复杂操作

例如释放大量 extent,无法假定一个 transaction 就能完成。XFS 使用以下机制:

一串 rolling transactions 本身不构成一个 crash-atomic transaction。 每个已经持久化的 transaction 可以单独恢复;需要跨 transaction 保证完成的工作依赖 intent/deferred-op 协议。

ext4 也会拆分长操作,并使用 orphan tracking 等机制处理特定 recovery 问题。但传统 JBD2 主要提供 block-level transaction,不理解“继续完成某个 extent 操作”这样的 filesystem-specific 工作。

4. Log space 回收的组织方式不同

JBD2 通过 checkpoint list 跟踪已 commit、但尚未完成 checkpoint 的 buffer,并根据 transaction 的完成状态回收 journal space。

XFS 使用 Active Item List(AIL) 跟踪仍需 log 保护的 item,按 LSN 组织。Metadata writeback 可以解除相应的 log 依赖;relogging 也可以将 item 的依赖移到更新的 LSN。

因此,XFS log tail 的推进不仅涉及 metadata writeback,还与 relogging、intent 的生命周期有关。AIL 中的 item 也不全是可以直接 writeback 的 metadata buffer。

两者都需要在修改开始前进行空间控制:JBD2 使用 journal credits,XFS 使用 log reservation。XFS 的 permanent reservation、rolling transaction 和 relogging 共同支持长操作的 forward progress。

5. File data 的一致性模式不同

ext4 提供三种主要模式:

XFS 不提供 file data journaling。它依赖 data I/O、unwritten extent conversion 以及相关 metadata update 的 ordering 来保证一致性,不能仅凭“都是 metadata journaling”就认为它与 ext4 data=writeback 的具体行为完全相同。

对应用而言,普通 write 返回不等于数据已经持久化,仍需使用 fsync() 等接口满足 durability 要求。对内核代码而言,xfs_trans_commit() 和 jbd2_journal_stop() 也不能直接理解成“journal 已经落盘”。

6. ext4 fast commit 是传统 block logging 之外的路径

启用 ext4 fast commit 后,“ext4 总是记录整个 metadata block”就不成立了。

Fast commit 在支持的 data=ordered 场景下,记录重建相关 metadata 所需的精简信息,而不是每次都写完整 metadata block。它仍与 JBD2 full commit 协作:遇到不支持的操作、fast commit space 不足或 full commit 定时触发等情况,会执行 full commit。

所以准确的比较是:

参考资料与源码入口

本站所有文章转发 CSDN 将按侵权追究法律责任,其它情况随意。