跳转至内容

Ext4

来自 ArchWiki

来自 Ext4 - Linux Kernel Newbies

Ext4 是最常用的 Linux 文件系统 Ext3 的演进。在很多方面,Ext4 对 Ext3 的改进比 Ext3 对 Ext2 的改进更深入。Ext3 主要是在 Ext2 上增加了日志功能,而 Ext4 则修改了文件系统重要的数据结构,例如用于存储文件数据的数据结构。其结果是一个设计更优、性能更好、可靠性更强、功能更丰富的文件系统。

创建新的 ext4 文件系统

安装 e2fsprogs

格式化分区请执行

# mkfs.ext4 /dev/partition

有关更多选项,请参阅 mke2fs(8)

提示 要查看/配置默认的 mke2fs 选项,请编辑 /etc/mke2fs.conf

每 inode 字节数比例

来自 mke2fs(8)

mke2fs 为磁盘上的每 bytes-per-inode 字节创建一个 inode。bytes-per-inode 比例越大,创建的 inode 就越少。

创建新文件、目录、符号链接等至少需要一个可用的 inode。如果 inode 数量太低,即使文件系统仍有剩余空间,也无法在该文件系统上创建任何文件。

由于文件系统创建后无法更改每 inode 字节数比例或 inode 数量,因此 mkfs.ext4 默认使用一个相对较低的比例,即每 16384 字节(16 KiB)分配一个 inode,以避免这种情况。

然而,对于大小为几百 GB 或几千 GB 且平均文件大小为兆字节范围的分区,这通常会导致过多的 inode 数量,因为创建的文件数量从未达到 inode 的数量。

这会导致磁盘空间浪费,因为所有未使用的 inode 各占文件系统上的 256 字节(这也在 /etc/mke2fs.conf 中设置,但不应更改)。256 字节 * 数百万 = 相当多的未使用 inode 浪费的 GB。

可以通过比较 dfdf -i 提供的 Use%IUse% 图来评估这种情况。

$ df -h /home
Filesystem              Size    Used   Avail  Use%   Mounted on
/dev/mapper/lvm-home    115G    56G    59G    49%    /home
$ df -hi /home
Filesystem              Inodes  IUsed  IFree  IUse%  Mounted on
/dev/mapper/lvm-home    1.8M    1.1K   1.8M   1%     /home

要指定不同的每 inode 字节数比例,请使用 -T usage-type 选项,它提示了文件系统预期的使用类型,使用 /etc/mke2fs.conf 中定义的类型。其中较大的类型包括 largefilelargefile4,它们分别提供每 1 MiB 和每 4 MiB 一个 inode 的更相关的比例。可以使用如下方式:

# mkfs.ext4 -T largefile /dev/device

每 inode 字节数比例也可以直接通过 -i 选项设置:例如,使用 -i 2097152 表示 2 MiB 比例,使用 -i 6291456 表示 6 MiB 比例。

提示 反之,如果设置一个用于托管数百万小文件(如电子邮件或新闻组项)的分区,请使用较小的 usage-type 值,例如 news(每 4096 字节一个 inode)或 small(相同,加上更小的 inode 和块大小)。
警告 如果大量使用符号链接,请确保使用较低的每 inode 字节数比例以保持足够的 inode 数量,因为虽然每个新的符号链接不占用更多空间,但会消耗一个新 inode,因此文件系统可能会很快耗尽它们。

预留块

默认情况下,文件系统块的 5% 将为超级用户保留,以避免碎片化并“允许根目录拥有的守护进程在非特权进程无法写入文件系统后继续正常运行”(摘自 mke2fs(8))。

对于现代大容量磁盘,如果分区用作长期存档或对系统操作不重要(如 /home),则此比例过高。有关 ext4 开发人员 Ted Ts'o 对预留块的看法,请参阅 此邮件;有关此主题的更广泛背景,请参阅 此 Superuser 回答

当分区为以下任一时,通常可以安全地降低预留块的百分比以释放磁盘空间:

  • 非常大(例如 > 50G)
  • 用作长期存档,即文件不会频繁删除和创建

ext4 相关工具的 -m 选项允许指定预留块的百分比。

要在创建文件系统时完全阻止预留块,请使用

# mkfs.ext4 -m 0 /dev/device

要将其更改为 1%(之后),请使用

# tune2fs -m 1 /dev/device

要将预留块空间设置为以千兆字节为单位的绝对大小,请使用 -r

# tune2fs -r $((ngigs * 1024**3 / blocksize)) /dev/device

blocksize 是文件系统块的大小(以字节为单位)。这几乎总是 4096;请务必检查。

# tune2fs -l /dev/device | grep 'Block size:'
Block size:               4096

$(()) 语法用于数学扩展。此语法在 bashzsh 中工作,但在 fish 中无效。对于 fish,语法是

# tune2fs -r (math 'ngigs * 1024^3 / blocksize') /dev/device

这些命令可以应用于当前已挂载的文件系统,并且更改会立即生效。使用 findmnt(8) 查找设备名称。

# tune2fs -m 1 "$(findmnt -no SOURCE /the/mount/point)"

要查询当前预留块的数量

# tune2fs -l /dev/mapper/proxima-root | grep 'Reserved block count:'
Reserved block count:     2975334

这是块的数量,因此需要将其乘以文件系统的块大小以获得字节或千兆字节的数量:2975334 * 4096 / 1024**3 = 11.34 GiB

从 ext2/ext3 迁移到 ext4

挂载 ext2/ext3 分区为 ext4 而无需转换

基本原理

在完全转换为 ext4 和简单地保留 ext2/ext3 之间的一种折衷方法是将分区挂载为 ext4。

优点

  • 兼容性(文件系统可继续作为 ext3 挂载)– 这允许用户仍然从其他不支持 ext4 的操作系统(例如,带有 ext2/ext3 驱动程序的 Windows)读取文件系统。
  • 提高性能(尽管不如完全转换的 ext4 分区)。[1] [2]

缺点

  • ext4 的较少功能被使用(仅那些不改变磁盘格式的功能,如多块分配和延迟分配)。
注意 除了 ext4 相对新颖(这可能被视为一种风险)之外,这种技术没有重大缺点

过程

  1. 编辑 /etc/fstab,将要挂载为 ext4 的任何分区的 'type' 从 ext2/ext3 更改为 ext4。
  2. 重新挂载受影响的分区。

将 ext2/ext3 分区转换为 ext4

基本原理

要体验 ext4 的优势,必须完成一个不可逆的转换过程。

优点

  • 提高性能和新功能。[3] [4]

缺点

  • 包含大部分静态文件(如 /boot 分区)的分区可能不会受益于新功能。此外,添加日志(将 ext2 分区迁移到 ext3/4 时隐含)总是会产生性能开销。
  • 不可逆(ext4 分区无法“降级”为 ext2/ext3。但是,直到 extent 和其他独特选项被启用之前,它是向后兼容的)。

过程

这些说明改编自 Kernel 文档 和一个 BBS 帖子

警告

在接下来的步骤中,/dev/sdxX 表示要转换的分区的路径,例如 /dev/sda1

  1. 备份要转换为 ext4 的任何 ext3 分区上的所有数据。对于根分区来说,一个有用的软件包是 clonezilla
  2. 编辑 /etc/fstab,将要转换为 ext4 的任何分区的 'type' 从 ext3 更改为 ext4。
  3. 启动 live 介质(如果需要)。使用 e2fsprogs 的转换过程必须在驱动器未挂载时进行。如果转换根分区,最简单的方法是使用其他 live 介质启动。
  4. 确保分区*未*挂载
  5. 如果转换 ext2 分区,第一个转换步骤是通过以 root 身份运行 tune2fs -j /dev/sdxX 来添加一个 日志;使其成为 ext3 分区。
  6. 以 root 身份运行 tune2fs -O extent,uninit_bg,dir_index /dev/sdxX。此命令将 ext3 文件系统转换为 ext4(不可逆)。
  7. 以 root 身份运行 fsck -f /dev/sdxX
    • 此步骤是必需的,否则文件系统*将无法读取*。此 fsck 运行是为了将文件系统恢复到一致状态。它将找到组描述符中的校验和错误 - 这是预期的。-f 选项要求 fsck 强制检查,即使文件系统看起来是干净的。可以在此基础上使用 -p 选项进行“自动修复”(否则,用户将被询问每个错误的输入)。
  8. 推荐:挂载分区并以 root 身份运行 e4defrag -c -v /dev/sdxX
    • 尽管文件系统现在已转换为 ext4,但转换前写入的所有文件尚未利用 ext4 的 extent 选项,这将提高大文件性能并减少碎片和文件系统检查时间。为了充分利用 ext4,所有文件都必须在磁盘上重写。使用 e4defrag 来处理此问题。
  9. 重启

提升性能

禁用访问时间更新

ext4 文件系统会记录文件最后访问时间的信息,并且记录它会产生一些开销。有关 noatime 及相关选项,请参阅 fstab#atime options

增加提交间隔

可以通过为 commit 选项提供更长的时间延迟来增加数据和元数据的同步间隔。

默认的 5 秒意味着如果断电,将丢失最多 5 秒的最新工作。由于日志功能,文件系统不会损坏。下面的 fstab 图示了 commit 的使用。

/etc/fstab
/dev/sda5    /    ext4    defaults,commit=60    0    1

关闭障碍

警告 不建议为没有电池备份缓存的磁盘禁用障碍,这可能导致严重的文件系统损坏和数据丢失。

Ext4 默认启用写障碍。它确保文件系统元数据被正确写入和排序在磁盘上,即使在写缓存断电时也是如此。这会带来性能成本,特别是对于大量使用 fsync 或创建和删除大量小文件的应用程序。对于有电池备份写缓存的磁盘,禁用障碍可以安全地提高性能。

要关闭障碍,请将 barrier=0 选项添加到所需文件系统中。例如

/etc/fstab
/dev/sda5    /    ext4    defaults,barrier=0    0    1

禁用日志

警告 在突然卸载(如断电或内核锁定)的情况下使用没有日志功能的文件系统可能导致数据丢失。

可以使用以下命令在未挂载的磁盘上使用 ext4 禁用日志

# tune2fs -O "^has_journal" /dev/sdXn

使用日志优化性能

LWN.net 上关于 Ext4 的快速提交 的文章引言简洁地总结了为什么以及如何使用 data=journaldata=writeback 挂载选项来提高 ext4 文件系统的整体性能,与默认的 data=ordered 操作模式相比。此外,通过添加 journal_async_commit 挂载选项也可以加快日志本身的性能。

注意 journal_async_commit 挂载选项*不适用于*默认的 data=ordered 挂载选项,因此请显式地使用不同的模式挂载 ext4_device;参阅 ext4(5) § data=

另一个选项是使用更新的日志格式,参阅 #启用 fast_commit

外部日志设备

如果使用非默认的 data= 选项,专用的日志设备在某些情况下也可能加快文件操作速度。例如,当一个相对慢的设备用于数据本身,而另一个(更快但更小)的设备用于日志时。设置单独的日志设备

# mke2fs -O journal_dev /dev/journal_device

要将 journal_device 指定为 ext4_device 的日志,请使用

# tune2fs -J device=/dev/journal_device /dev/ext4_device

如果要在 ext4_device 上创建新文件系统,请将 tune2fs 替换为 mkfs.ext4

使用 /etc/fstab 中的 x-systemd.requires 挂载选项将 journal_device 添加为 ext4_device 的依赖项。

/etc/fstab
/dev/ext4_device    /    ext4    defaults,x-systemd.requires=/dev/journal_device    0    1

这可以防止 journal_device 需要任何设置(例如,它已加密)时出现问题。

注意 日志设备的 UUID 和设备号都保存在 ext4 文件系统中。加载日志设备时,仅使用设备号,这会导致问题,因为磁盘重新排列时设备号会更改。Linux 将拒绝挂载指向错误设备的(文件)系统,但以下解决方法可能仍然有用

忽略保存的设备号,并使用 journal_path 挂载选项通过路径强制加载日志

/etc/fstab
/dev/ext4_device    /    ext4    defaults,x-systemd.requires=/dev/journal_device,journal_path=/dev/journal_device    0    1

e2fsck 将使用 UUID 查找日志设备,并在保存的设备号不同步时修复它。但是,它会将此视为损坏,并触发不必要的完整文件系统扫描 [5]。可以在 e2fsck配置文件 中禁用此设置。

/etc/e2fsck.conf
[problems]
# PR_0_EXTERNAL_JOURNAL_HINT: Superblock hint for external superblock should be xxxx
0x000033 = {
    # Tell e2fsck that if this problem is encountered, it can be fixed but should
    # not be considered corruption, the filesystem should still be marked clean.
    not_a_fix = true
}

技巧与提示

使用基于文件的加密

自 Linux 4.1 起,ext4 原生支持文件加密,请参阅 fscrypt 文章。加密是在目录级别应用的,不同的目录可以使用不同的加密密钥。这与 dm-crypt(块设备级别加密)和 eCryptfs(堆叠加密文件系统)不同。

在现有文件系统中启用元数据校验和

当文件系统是用 e2fsprogs 1.43(2016 年)或更高版本创建时,元数据校验和默认启用。现有文件系统可以转换为启用元数据校验和支持。

要详细了解元数据校验和,请参阅 ext4 wiki

提示 使用 dumpe2fs 检查文件系统启用的功能。
# dumpe2fs -h /dev/path/to/disk
注意 文件系统必须未挂载。

首先需要使用 e2fsck 检查和优化分区。

# e2fsck -Df /dev/path/to/disk  

将文件系统转换为 64 位

# resize2fs -b /dev/path/to/disk 

最后启用校验和支持

# tune2fs -O metadata_csum /dev/path/to/disk

要验证

# dumpe2fs -h /dev/path/to/disk | grep features:
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype extent 64bit flex_bg sparse_super large_file huge_file dir_nlink extra_isize metadata_csum

使用 LVM 时的维护

e2scrub 工具会检查 ext4 文件系统的元数据,如果它在 LVM 逻辑卷中使用。卷组必须有 256MiB 的未分配空间才能进行此检查,因为该工具会创建一个快照进行检查。正如 e2scrub(8) 手册所指出的,该工具不修复错误,而是报告它们并标记文件系统以要求在下次挂载前进行 e2fsck(请参阅 e2fsck(8))运行。

检查可以自动化,例如通过 启用 打包的 e2scrub_all.timer 单元。

如果缺少最少的 256MiB 未分配空间,请参阅 LVM#一次性调整逻辑卷和文件系统的大小

启用 fast_commit

ext4 的“fast commits”功能引入了一种新的、更轻量级的日志记录方法。预计这将显著提高 ext4 文件系统的性能,[6]

要在新文件系统上启用此功能,请在 -O 文件系统选项参数中包含 fast_commit

要在现有文件系统上启用此功能,请运行

# tune2fs -O fast_commit /dev/drivepartition

要查询当前配置

# tune2fs -l /dev/drivepartition | grep features

要在现有文件系统上禁用此功能,请运行

# tune2fs -O '^fast_commit' /dev/drivepartition

启用不区分大小写的模式

警告
  • 如果启用了 casefold 功能,则无法可靠地将其关闭(由于 tune2fs 中可能存在错误)。在启用它之前,请注意以下限制!
  • GRUB 目前不支持 ext4 的 casefold 功能;请参阅 GRUB bug #56897。为 GRUB 需要读取的文件系统启用它将导致系统无法启动,并出现无用的 unknown filesystem 错误,即使没有目录实际使用该功能。
  • casefold 功能与 overlayfs 不兼容,这可能阻止类似 DockerPodman 的容器软件在该文件系统上工作。高级 systemd 功能,如 systemd-sysext(8) 扩展映像也可能变得不可用。

ext4 可以在不区分大小写的模式下使用,这可以提高在 Wine 中运行的应用程序和游戏的性能。此功能不会影响整个文件系统,只影响启用了不区分大小写属性的目录。

首先,在文件系统中启用该功能

# tune2fs -O casefold /dev/path/to/disk

在任何目录中启用不区分大小写的 属性

$ chattr +F /mnt/partition/case-insensitive-directory

请注意,目录必须为空,从其他地方移动子目录不会导致它们继承该属性,因此请相应地提前计划。

参见