5.1 EXT2 文件系统
The 2nd Extended File System.
5.1.1 EXT2 的数据结构
EXT2 文件系统格式化时,Inode 与块的数量就 确定 了,每个块都有自己的编号,以便区分和定位。需要时可以用 resize2fs
等命令修改文件系统大小 。

块
EXT2 所支持的块大小为 1K,2K 及 4K 。
Block 大小 | 1 KB | 2 KB | 4 KB |
---|---|---|---|
最大单一文件限制 | 16 GB | 256 GB | 2 TB |
最大文件系统总容量 | 2 TB | 8 TB | 16 TB |
📕虽然 EXT2 支持 2 GB 以上的文件,但某些应用程序只能使用 2 GB 以下的文件。
Boot Block
EXT2 的头 1024 Bytes 称为 Boot Block,引导块,预留给 VBR,即分区的引导扇区,不受 EXT2 文件系统的管理。
Block Group
其余的空间被划分为多个块,这些块被编成 块组,即 Block Groups(BG)。任何给定文件的数据通常都尽可能地包含在一个块组中,这样,在读取连续大文件时,会减少磁盘寻道次数。
每个块组包含:
-
超级块:1 个块
-
块组描述符表:N 个块
-
块位图:1 个块
-
Inode 位图:1 个块
-
Inode 表:N 个块
-
数据块:N 个块
超级块
超级块 用于记录文件系统的 整体 信息:
-
块与 Inode 的总数
-
块与 Inode 已用、可用数量
-
块与 Inode 的大小
-
文件系统的挂载时间、最近写入数据的时间、最近校验的时间
-
文件系统当前挂载状态:称 Valid Bit,
0
表示已挂载,1
表示未挂载
超级块 保存在整个系统 第一个 BG 中,后续的每个块组都会在开头保存超级块的 复本,以备不时之需。
通常在系统启动中使用的是文件系统中第一个 超级块。
块组描述符表
Group Descriptor Table
这张表包含了 整个系统所有块组的信息,由一个接一个的块组描述符组成。每个块组都包含这张表的复本,紧跟超级块,作用也一样,用于修复系统。
正常工作时 EXT2 只使用第一个复本,即块组0 中的。
- 块组描述符包含:
该块组的块位图、Inode 位图、Inode 表的位置,可用块数量,可用 Inode 数量,已用目录数量。
块位图
Block Bitmap
该块组中块的分配位图,每一位代表一个块的当前状态,1 为已用,0 为可用。据此位图来分配或回收块。
Inode 位图
该块组中 Inode 的分配位图,工作方式同块位图。据此位图来分配或回收 Inode。
Inode 表
Inode 表是当前块组中所有 Inode 的集合,用于追踪块组中所有文件的元数据。
该表会被操作系统频繁地访问,因此应尽可能减少读取该表所用的时间。
5.1.2 EXT2 的缺点
-
块的数量是 固定 的
-
每个块最多只能放 一个文件 的数据;
-
若文件大于块的大小,则一个文件会占用 多个块
-
若文件小于块,块的剩余容量无法再次利用,浪费
5.2 EXT3 文件系统
The 3rd Extended File System.
5.2.1 引入日志系统
EXT3 引入了日志系统,并支持把日志保存在单独的文件系统中。
在 EXT2 中,写资料到硬盘中时,先将资料写入缓存中,当缓存写满时才会写入硬盘中。
在 EXT3 中,写资料到硬盘中时,先将资料写入缓存中,待缓存写满时系统先通知日志系统,再将资料写入硬盘,完成后再通知日志系统,资料已完成写入工作。
系统开机时会检查日志是否有错误,加快启动速度。
5.2.2 EXT3 优点
可用性
非正常关机后,只有通过 e2fsck
进行一致性校验后,EXT2 才能被装载使用。运行 e2fsck 的时间取决于 EXT2 文件系统的大小。校验几十 GB 的文件系统需要很长时间。如果文件数量多,校验的时间则更长。极大地限制了可用性。
相比之下,除非发生硬件故障,即使非正常关机,EXT3 也不需要文件系统校验。因为数据写入磁盘的过程保证了文件系统的一致性。在非正常关机后,恢复 EXT3 文件系统的时间不依赖于文件系统的大小或文件数量,而决定于维护一致性所需 “日志” 的大小。使用缺省日志设置,恢复时间仅需一秒(依赖于硬件速度)。
数据完整性
使用 EXT3 文件系统,在非正常关机时,数据完整性能得到可靠的保障。
可以选择数据保护的类型和级别:
可以选择保证文件系统一致,但是允许文件系统上的数据在非正常关机时受损。
也可以选择保持数据的可靠性与文件系统一致,为默认设置。
速度
尽管 EXT3 写入数据的次数多于 EXT2,但是 EXT3 常常快于 EXT2(高数据流)。这是因为 EXT3 的日志功能优化硬盘磁头的转动。
可以从 3 种日志模式中选择一种来优化速度,有选择地牺牲一些数据完整性。
易于迁移
从 EXT2 迁移至 EXT3 时可以不格式化硬盘。
5.3 EXT4 文件系统
The 4th Extended File System.
从 EXT3 在线迁移到 EXT4,无须重新格式化。
5.3.1 新特性
Extent
EXT3 采用间接块映射,当操作大文件时,效率极其低下。EXT4 引入了 EXTENT 概念,提高效率,每个 EXTENT 为一组连续的数据块,效率更高。
多块分配
向 EXT3 写入数据时,每次只能分配一个块,写一个文件往往要调用多次 “数据块分配器”,而 EXT4 的多块分配器 Multi-Block Allocator(mballoc)一次可分配多个数据块,效率更高。
延迟分配
EXT3 的数据块分配策略是尽快分配,而 EXT4 是尽可能地延迟分配,直到文件在缓存中写完才开始分配数据块,并写入磁盘。
延迟分配优化了文件的数据块分配,显著提升性能。
快速校验
早期的 fsck
要检查所有的 Inode ,因此很慢。EXT4 给每个组(Allocation Group)的 Inode 表中都添加了一份可用 Inode 列表,这样,在执行 fsck
时就可以跳过它们,而只去检查在用的 Inode,实现文件系统的快速校验。
日志校验
日志区被频繁读取,极易导致磁盘硬件故障,而从损坏的日志中恢复数据会导致更多的数据损坏。
EXT4 的日志校验功能可以很方便地判断日志数据是否损坏,将过去两阶段日志机制合并成一个阶段,提高性能。
无日志模式
EXT4 允许关闭日志,以便有特殊需求的用户可以借此进一步提升性能。
在线碎片整理
EXT4 支持在线碎片整理,并提供 e4defrag
工具,针对个别文件或整个文件系统进行碎片整理。
更大的 Inode
EXT4 支持更大的 Inode,EXT3 默认 Inode 大小为 128 Bytes,EXT4 默认 Inode 大小为 256 字节。
持久预分配
Persistent PreAllocation
P2P 软件为了保证下载文件有足够的空间存放,常常会预先创建一个与所下载文件大小相同的空文件,以免未来的数小时或数天之内磁盘空间不足导致下载失败。EXT4 在文件系统层面实现了持久预分配,并提供相应的 API,比应用软件自己实现更有效率。
默认启用 BARRIER
Ext4 默认启用 barrier,只有当 barrier 之前的数据全部写入磁盘,才能写 barrier 之后的数据。
磁盘上配有内部缓存,以便重新调整批量数据的写操作顺序,优化写入性能,因此文件系统必须在日志数据写入磁盘之后才能写改动记录,若改动记录写入在先,则日志有可能损坏,数据一致性会遭到破坏。
5.4 EXT 家族的缺点
-
EXT 文件系统在格式化前,必须预先规划 出所有的 Inode、block、元数据等信息,而 无法动态配置,格式化很慢。
-
同一文件系统只能使用相同大小的 Inode。
-
性能差,不足以支持大容量磁盘和大文件。
5.5 XFS 文件系统
CentOS 7 开始,默认的文件系统为 XFS。
-
XFS 是一个高性能的 64 位 日志式文件系统,擅长 并行的 I/O 操作,归功于其设计优秀的 AG 机制,因此特别 擅长处理大文件。
-
同一文件系统 跨越不同存储设备 时,在 I/O 线程、文件系统带宽、文件大小、文件系统大小方面具有 极强的伸缩性。
-
XFS 通过 元数据日志 及 Write Barrie 来保证 数据一致性。
-
通过保存在 B+ 树中的 Extent 来分配存储空间。
-
延迟分配 帮助文件系统防止碎片化,支持 在线整理碎片,
xfs_fsr
命令来实现。 -
对于某些硬件来说,支持 I/O 带宽的预分配。
-
xfs_growfs
命令可以在线扩展文件系统的大小。 -
XFS 提供了
xfsdump
和xfsrestore
这两个原生备份/恢复工具。 -
XFS 文件系统无法被收缩。
5.5.1 XFS 的日志系统
XFS 日志保存的是 逻辑条目,以人类更加容易理解的方式来描述当前正在进行的操作(物理日志与其相反,保存的是每次操作中被修改的块)。
如果发生系统崩溃,可以根据日志中的记录来重做崩溃前一时刻的系统操作。崩溃之后首次挂载文件系统时,会自动进行恢复。恢复的速度不受文件系统大小的影响,取决于需要重做的系统 操作的数量。
元数据日志
XFS 对 文件系统元数据 提供了日志支持。
当文件系统更新时,元数据会在实际的磁盘块被更新之前顺序写入日志。
日志的保存与性能
XFS 的日志保存在磁盘块的 循环缓冲区 上,不受文件系统操作的影响。
XFS 日志大小的上限是 64k 个块和 128 MB 中的较大值,下限取决于已存在的文件系统和目录的块的大小。
日志的更新以 异步 的方式进行,以免影响整体性能。如果在运行中,日志写入被要求以同步方式提交,则日志必须完全写入之后,才能开始实际的写入操作,就会影响整体性能。
内置日志
XFS 文件系统创建时 默认使用内置日志,把日志和文件系统数据放置在 同一个块设备 上。
由于在所有的文件系统写入发生前都要更新日志中的元数据,内置日志可能导致磁盘竞争。在大多数负载下,这种等级的竞争非常低以至于对性能没有影响。但对于沉重的随机写入负载,比如在忙碌的数据块服务器上,XFS 可能因为这种 I/O 竞争 无法获得最佳性能。
外置日志
如果确实需要最佳的文件系统性能,XFS 提供了一个选项,允许 把日志放置在一个分离的物理设备上。
这只需要很小的物理空间。分离的设备有自己的 I/O 路径,如果该设备能对同步写入提供低延迟的路径,那么它将给整个文件系统的操作带来显著的性能提升。
SSD,或带有回写缓存的 RAID 系统是日志设备的合适候选,它们能满足这种性能要求。不过后者在遭遇断电时可能降低数据的安全性。要启用外部日志,只须以 logdev
选项挂载文件系统,并指定一个合适的日志设备即可。
5.5.2 XFS 的特点
AG
Allocation Groups,分配组,AG
文件系统被分成多个 AG,它们是文件系统中的 等长线性存储区。
-
一个 AG 好比一个 子文件系统,每个 AG 各自管理各自的 Inode 和可用空间,以 提升并行性能。
-
AG 的数量和大小是由
mkfs.xfs
指定的,因此文件系统通常被划分为 少量的、等长的 AG。 -
AG 的数量直接决定了 给文件分配块时 并行的数量。
在内存经常不够用,而且要进行大量块分配的情况下,应该增加 AG 的数量。但也不能过多,会造成大量的 CPU 时间被文件系统占用,尤其在文件系统快用光的时候。需要时可以用 xfs_growfs
来增加 AG。
-
同一时刻、同一个 AG 中,只能进行一次写操作,但 多个 AG 可以同时进行多个写操作。
-
文件和文件夹可以跨越 AG,该机制为 XFS 提供了 可伸缩性 和 并行 特性,多个线程和进程可以同时在同一个文件系统上执行 I/O 操作。
在多核 CPU 系统中,多个 CPU 可以同时写入不同的 AG,在一个文件系统中,物理实现了并行处理多个磁盘操作,因此特别适用于跨越多设备的文件系统,允许对底层存储设备吞吐量进行优化使用。
Write Barrier
Write Barrier,写屏障,是一种内核机制,可以保证文件系统 元数据 正确有序地写入持久存储设备,在设备掉电的情况也能保证。
XFS 挂载时默认开启写屏障,该功能会使底层存储设备的回写缓存在适当的时候被冲刷,尤其对 XFS 日志进行写操作的时候。该功能的目的是保证文件系统的一致性,其部署是针对特定设备的,因为并非所有底层的硬件都支持冲刷缓存的请求。
Extent

-
XFS 文件系统中的文件用到的块由 变长 Extent 管理,每个 Extent 描述了一个或多个 连续的块。
-
一个文件可以由 0 或多个 Extent 组成,一个文件碎片就需要一个 Extent。一个文件的物理大小一定是 Extent 容量的 整数倍。
一般来说,当进程创建文件的时候,文件系统管理程序会将 整个 Extent 分配给该文件。当再次向该文件写入数据时 (有可能是在其他写入操作之后),数据会从上次写入的数据 末尾处追加 数据。这样 可以减少甚至消除文件碎片。
-
Extent 只需保存 起始块编号 和 块数量 即可,无需像传统方式一样保存所有的块编号。
-
Extent 的大小
Extent 的大小需在格式化时事先指定,最小 4K,最大 1G。非 RAID 的磁盘默认为 64 K,而具有类似 RAID 的 Stripe 情况下,则建议 Extent 设置为与 Stripe 一样大。
B+ Tree
EXT2 文件系统用块位图管理空间分配,在 XFS 中不使用位图,而使用 一对 B+ Tree。
一个 B+ Tree 用于索引可用的 Extent 长度,另一个索引这些 Extent 的 起始块。
这种 双索引策略 使得文件系统在定位可用空间的 Extent 时十分高效。
Delayed Allocation
Delayed Allocation,延迟分配,也称 Allocate-on-flush,缩写 DelAlloc,是 XFS 操作系统的一个特性。
XFS 在文件空间分配上使用了惰性计算技术。当一个文件被写入缓存时,XFS 简单地在内存中对该文件保留合适数量的块,而不是立即给数据分配 Extent。实际的块分配仅在这段数据被 冲刷 到磁盘时才发生。这一机制 提高了将这一文件写入一组连续的块中的机会,减少了碎片,提升了性能。
当需要为即将写入的数据分配块时,会 从可用空间计数器中 把要分配的部分 减掉,但实际上并未真正的在可用空间位图中予以分配。
冲刷的时机
事实上,要写入磁盘的这部分数据 一直驻留在内存中,直到以下情况才会被扔到磁盘中:
-
内存不够用的时候
-
当内核决定抛弃过期的缓存时
-
运行
sync
来同步数据时
块分配过程
延迟分配把文件的块分配分成了 两个阶段:
预定:把数据写入缓存,预定磁盘空间
-
减少可用块计数器
-
创建一个虚拟的 DelAlloc Extent
分配:从内存保存到磁盘时,分配块。
- 把虚拟 DelAlloc Extent 转换为真实的 Extent
延迟分配的优点
-
组合写入、分配大块的 Extent,减少了磁盘碎片
-
短期生存的文件可能根本无需分配磁盘空间,减少不必要的磁盘操作
-
可以为随机写入的文件分配连续的空间,减少了磁盘碎片
-
延迟处理的流程 减少了 CPU 的使用率,尤其适用于缓慢生长的文件
扩展属性
XFS 通过扩展文件属性给文件提供了多个数据流,使文件可以被附加多个属性,格式均为 “名称 - 值”。
这些属性被分到两个命名空间中:root 和 user。保存在 root 命名空间中的属性只允许被超级用户修改,user 空间中的属性可被任何拥有写权限的人修改。
XFS 中,扩展属性可以被添加到任何类型的 Inode 中,attr
命令用于控制扩展属性。
xfsdump
和 xfsrestore
命令可以识别扩展属性,备份和恢复数据时都会包含这些属性。
直接 I/O
对于需要 高吞吐量 的应用,XFS 实现了直接的 I/O,允许 未缓存的 I/O 操作直接应用到用户空间。数据在应用程序的缓冲区和磁盘间利用 DMA 进行传输,以此提供底层磁盘设备全部的 I/O 带宽。
DMA,Direct Memory Access,直接内存访问。很多硬件支持不通过 CPU,而直接与内存交换数据。通常先由 CPU 发出控制指令,待硬件与内存达成正常通信以后,就可以不经过 CPU 而直接与内存通讯,解放了 CPU,降低 CPU 利用率。
xfsdump
xfsdump 是 XFS 的原生备份、恢复工具,它按 Inode 顺序备份 XFS 文件系统。
与传统的 UNIX 文件系统不同,XFS 无需卸载 文件系统。对在用的 XFS 文件系统做 dump 就可以保证镜像的一致性。这与 XFS 对快照的实现不同,XFS 的 dump 和 restore 的过程是 可以被中断 然后继续的,无须冻结文件系统。
5.5.3 XFS 结构
XFS 是日志式文件系统,最早被用于大容量磁盘以及高性能文件系统,很适合现在的系统环境。而且几乎具备 EXT4 所有功能。
XFS 文件系统数据分三部分:
-
数据区
-
日志区
-
实时运行区
数据区
Data Section
文件系统元数据(Inode、目录文件、间接块)、普通用户非运行文件、日志(内部日志)都保存在数据区。
数据区被划分为若干个 AG。
日志区
Log Section
日志区主要用于 记录 文件系统的 变化。当文件的变化被完整的写入到数据区后,该笔记录才会被终结。需要时可以借此更快速的修复文件系统。
日志区的 磁盘活动很频繁,系统允许指定高速的 外部磁盘 来作日志区,如 SSD。
实时区
Realtime Section
实时区用于保存实时运行的文件数据,在这类文件刚刚被创建、写入任何数据之前,xfsctl
会为该文件设置一个属性位。
实时区被划分为若干个等长的 Extent。
创建文件时,XFS 会在这个区段里找一个或多个 Extent 块,把文件先放在这些块里,分配完毕以后,再写到数据区。
超级块内容
-
isize:Inode 大小
-
agcount:AG 数量
-
agsize:AG 大小
-
sectsz:逻辑扇区的大小
-
bsize:块大小
-
blocks:块数量
-
sunit、swidth:RAID 的 stripe 参数
-
internal:日志区使用的是内置分区,而不是外置硬盘
-
extsz:Extent 容量
5.5.4 扩展 XFS 文件系统
xfs_growfs
是文件系统扩展命令,目的是让系统 充分利用后续没有用到的磁盘空间。
xfs_growfs /mnt
如果真的用在文件系统上面,再次挂载前,必须了解每种文件系统的挂载要求。