XFS
XFS 是由 Silicon Graphics, Inc. 创建的高性能日志文件系统。XFS 因其基于分配组的设计,在并行 I/O 方面尤为擅长。这使得 I/O 线程、文件系统带宽、文件和文件系统大小在跨越多个存储设备时具有极高的可伸缩性。
准备工作
要获取 XFS 用户空间工具,请安装 xfsprogs 包。它包含管理 XFS 文件系统所需的工具。
创建
要在 device 上创建新文件系统,请使用
# mkfs.xfs device
示例输出:
meta-data=/dev/device isize=256 agcount=4, agsize=3277258 blks
= sectsz=512 attr=2
data = bsize=4096 blocks=13109032, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0
log =internal log bsize=4096 blocks=6400, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
- 可选地,使用
-L label选项为文件系统分配标签。 - 在 mkfs.xfs 的块设备上使用该命令,如果设备上已存在文件系统,请添加
-f选项以覆盖该文件系统。[3]. 此操作将销毁先前文件系统中的所有数据。
校验和
xfsprogs 3.2.0 引入了一种新的磁盘格式 (v5),其中包括一个名为 自描述元数据 的元数据校验和方案。它基于 CRC32,可以提供额外的保护,防止元数据损坏(例如,在意外断电时)。使用 xfsprogs 3.2.3 或更高版本时,默认启用校验和,但可以通过在调用 mkfs.xfs(8) 时使用 -m crc=0 开关来禁用(对于旧内核上的读写挂载是必需的)。
# mkfs.xfs -m crc=0 /dev/target_partition
XFS v5 磁盘格式从 Linux Kernel 3.15 开始被认为是稳定的,可用于生产工作负载。
空闲 i 节点 b-tree
从 Linux 3.16 开始,XFS 添加了一个跟踪空闲 i 节点的 b-tree。它等同于现有的 i 节点分配 b-tree,不同之处在于空闲 i 节点 b-tree 跟踪至少有一个空闲 i 节点的 i 节点块。目的是改进 i 节点分配时查找空闲 i 节点簇的性能。它提高了老化文件系统(即几个月或几年的使用后,您向文件系统添加和删除了数百万个文件)的性能。使用此功能不会影响整体文件系统的可靠性级别或恢复能力。
此功能依赖于新的 v5 磁盘格式,该格式从 Linux Kernel 3.15 开始被认为是稳定的,可用于生产工作负载。它不会更改现有的磁盘结构,而是添加了一个新的结构,该结构必须与 i 节点分配 b-tree 保持一致;因此,旧内核只能以只读方式挂载具有空闲 i 节点 b-tree 功能的文件系统。
使用 xfsprogs 3.2.3 或更高版本时,默认启用此功能。如果您需要支持旧内核的可写文件系统,可以在格式化 XFS 分区时使用 finobt=0 开关禁用它。您需要同时使用 crc=0。
# mkfs.xfs -m crc=0,finobt=0 /dev/target_partition
或简而言之(因为 finobt 依赖于 crc)
# mkfs.xfs -m crc=0 /dev/target_partition
反向映射 b-tree
反向映射 b-tree 其核心是
- 存储空间使用情况的辅助索引,它有效地提供了主空间使用情况元数据的一个冗余副本。这会增加一些文件系统操作的开销,但将其包含在文件系统中可以使交叉引用非常快速。它是在线修复文件系统的关键功能,因为我们可以从辅助副本重建损坏的主元数据。
- 该功能在 Linux 4.16 中已从 EXPERIMENTAL 状态毕业,可用于生产。但是,在线文件系统检查和修复是(到目前为止)该功能的唯一用例,因此至少要等到在线检查毕业到生产就绪状态,它才能成为默认选项。
- 反向映射 b-tree 将文件系统块映射到文件系统块的所有者。大多数映射将指向 i 节点号和偏移量,但也存在指向文件系统元数据的映射。此辅助元数据可用于验证主元数据,或在发生磁盘错误时精确定位丢失的数据。
从 xfsprogs 6.5.0 开始,此功能对新文件系统是默认启用的。
大时间戳
从 Linux 5.10 开始,XFS 支持使用重构的“时间戳和 i 节点编码函数,将时间戳作为 64 位纳秒计数器和位移来处理,以增加有效大小。这使得 XFS 能够轻松应对 2038 年问题,并支持到 2486 年。创建启用 bigtime 的新 XFS 文件系统,时间戳范围从 1901 年 12 月到 2486 年 7 月,而不是 1901 年 12 月到 2038 年 1 月。”该功能还将使配额计时器到期范围从 1970 年 1 月到 2486 年 7 月,而不是 1970 年 1 月到 2106 年 2 月。
从 xfsprogs 5.15 开始,大时间戳对新文件系统是默认启用的。
升级
使用 xfs_info(8) 验证现有文件系统是否启用了 bigtime。
# xfs_info / | grep bigtime ... bigtime=0 ...
使用 xfsprogs 5.11 及更高版本,您可以使用 xfs_admin(8) 升级现有(未挂载)文件系统。
# xfs_admin -O bigtime=1 device
或使用 xfs_repair(8)。
# xfs_repair -c bigtime=1 device
同时,您可能还想启用 inobtcount(另一个新默认值)。
性能
来自 XFS FAQ
- 默认值已经针对最佳性能进行了优化。mkfs.xfs 将检测单磁盘和 MD/DM RAID 设置之间的差异,并更改其使用的默认值以适当地配置文件系统。
- 在大多数情况下,您需要为
mkfs.xfs考虑的唯一事情是为硬件 RAID 设备指定条带单元和宽度。
(请参阅 #Stripe size and width)
largeio、swalloc、增加 logbsize 和 allocsize 等值,可能会获得性能提升。以下文章可能提供有关这些标志的更多详细信息
- 对于挂载选项,唯一会显著改变元数据性能的是
logbsize挂载选项。增加logbsize会减少给定工作负载的日志 I/O 次数。这种元数据性能提升的代价是,在系统崩溃并进行修改时,恢复后可能会“丢失”更多操作。
- 从内核 3.2.12 开始,默认的 I/O 调度程序 CFQ 会削弱 XFS 的大部分并行化能力。
因此,为了获得最佳性能,在大多数情况下,您只需按照 #Creation 的说明进行操作即可。
条带大小和宽度
如果此文件系统将部署在条带化 RAID 上,则可以通过指定条带大小给 mkfs.xfs(8) 命令来获得显著的速度提升。
XFS 有时可以检测到软件 RAID 下的几何结构,但如果您重新调整了它或正在使用硬件 RAID,请参阅 如何计算正确的 sunit,swidth 值以获得最佳性能。
访问时间
在某些文件系统上,可以通过在 /etc/fstab 文件中添加 noatime 挂载选项来提高性能。对于 XFS 文件系统,“默认的 atime 行为是 relatime,它与 noatime 相比几乎没有开销,但仍然维护有用的 atime 值。自 2.6.30 版本以来,所有 Linux 文件系统现在都默认使用此行为,因此出于性能原因,没有人真正需要对 XFS 使用 noatime。”[7]
有关此主题的更多信息,请参阅 Fstab#atime options。
丢弃
尽管 XFS 自内核 4.7 起支持异步丢弃[8][9][10],但 xfs(5) 仍然建议“使用 fstrim 应用程序来丢弃未使用的块,而不是 discard 挂载选项,因为此选项的性能影响相当严重。”
请参阅 Solid state drive#Periodic TRIM。
碎片整理
尽管 XFS 的 extent(区段)为基础的性质和它使用的延迟分配策略显著提高了文件系统抵抗碎片问题的能力,但 XFS 提供了一个文件系统碎片整理工具(xfs_fsr,XFS 文件系统重组器的缩写),可以对已挂载的活动 XFS 文件系统上的文件进行碎片整理。定期查看 XFS 碎片情况可能很有用。
xfs_fsr(8) 改进了挂载文件系统的组织。重组算法一次处理一个文件,压缩或以其他方式改进文件 extent(连续的文件数据块)的布局。
检查碎片级别
要查看文件系统的碎片程度
# xfs_db -c frag -r /dev/partition
执行碎片整理
要开始碎片整理,请使用 xfs_fsr(8) 命令。
# xfs_fsr /dev/partition
去重
reflink 功能自内核版本 4.9 起可用,并且自 mkfs.xfs 版本 5.1.0 起默认启用,它允许创建文件的快速 reflink 副本,以及事后进行重复数据删除,这与 btrfs 类似。
Reflink 副本
Reflink 副本最初不占用额外空间
$ cp --reflink bigfile1 bigfile2
直到其中一个文件被编辑,并发生写时复制。这对于创建(大型)文件的快照非常有用。
去重
可以使用 `duperemove` 等工具或 `util-linux` 包中的 `hardlink`(hardlink(1))对现有文件系统进行重复数据删除。
外部 XFS 日志
在例如 SSD 上使用外部日志(元数据日志)可能有助于提高性能 [11]。有关 logdev 参数的详细信息,请参阅 mkfs.xfs(8)。
要在创建 XFS 文件系统时保留指定大小的外部日志,请向 mkfs.xfs 命令指定 -l logdev=device,size=size 选项。如果省略 size 参数,则使用基于文件系统大小的日志大小。要挂载 XFS 文件系统以使用外部日志,请向 mount 命令指定 -o logdev=device 选项。
同步间隔
XFS 有一个专用的 sysctl 变量用于设置 写回间隔,默认值为 3000。
/etc/sysctl.d/20-xfs-sync-interval.conf
fs.xfs.xfssyncd_centisecs = 10000
管理
调整大小
XFS 可以使用 xfs_growfs(8) 在线调整大小。
# xfs_growfs -D size /path/to/mnt/point
如果省略 -D size,则文件系统会自动增大到可能的最大尺寸,即分区的大小。
在线元数据检查 (scrub)
xfs_scrub 要求内核检查 XFS 文件系统中的所有元数据对象。元数据记录会被扫描以查找明显错误的值,然后与其他元数据进行交叉引用。目标是通过检查单个元数据记录相对于文件系统中其他元数据的一致性,来建立对整个文件系统一致性的合理信心。如果存在完好的冗余数据结构,则可以从其他元数据重建损坏的元数据。
启用/启动 xfs_scrub_all.timer 以定期检查所有 XFS 文件系统的在线元数据。
修复
请参阅 Checking and Repairing an XFS File System、Which factors influence the memory usage of xfs_repair? 和 XFS Repair。
数据恢复
即使以只读模式(mount -o ro)挂载,如果 XFS 文件系统未干净地卸载,其日志仍会重放。
可能存在这种情况:损坏的 XFS 文件系统位于损坏的存储设备上,应以只读方式挂载,以便可以尝试从其复制文件而不造成进一步损坏,但由于未干净地卸载且损坏程度导致日志无法重放而无法挂载。另请考虑重放日志意味着写入损坏的文件系统,这本身可能不是个好主意。
要以完全不写入文件系统且不重放日志的方式挂载 XFS 文件系统,请使用 mount -o ro,norecovery。
恢复删除
xfs_undelete-gitAUR 可以在未挂载或以只读方式挂载的 XFS 文件系统上(在某些条件下)恢复已删除的文件。有关更多信息,请参阅 https://github.com/ianka/xfs_undelete。
故障排除
根文件系统配额
XFS 配额挂载选项(uquota、gquota、prjquota 等)在重新挂载文件系统时会失败。要为根文件系统启用配额,必须将挂载选项作为 rootflags= 内核参数传递给 initramfs。之后,它不应出现在根(/)文件系统的 /etc/fstab 的挂载选项中。
如果用户 "nobody" 无法访问挂载点,xfs_scrub_all 会失败
运行 xfs_scrub_all 时,它将为每个已挂载的 XFS 文件系统启动 xfs_scrub@.service。该服务以用户 nobody 身份运行,因此如果 nobody 无法导航到目录,它将以错误失败
xfs_scrub@mountpoint.service: Changing to the requested working directory failed: Permission denied xfs_scrub@mountpoint.service: Failed at step CHDIR spawning /usr/bin/xfs_scrub: Permission denied xfs_scrub@mountpoint.service: Main process exited, code=exited, status=200/CHDIR
要允许服务运行,请更改挂载点的权限,使用户 nobody 具有执行权限。
基于 systemd 的 initramfs 中 fsck.xfs 失败
在使用没有 base hook 的 mkinitcpio 生成的基于 systemd 的 initramfs 时,您将在 journal 中看到以下消息
systemd-fsck[288]: fsck: /usr/bin/fsck.xfs: execute failed: No such file or directory systemd-fsck[286]: fsck failed with exit status 8. systemd-fsck[286]: Ignoring error.
这是因为 fsck.xfs(8) 是一个 shell 脚本,需要 /bin/sh 来执行。/usr/bin/sh 由 base hook 提供,因此解决方案是将其添加到 /etc/mkinitcpio.conf 中的 HOOKS 数组前面。例如:
HOOKS=(base systemd ... )
参见
- XFS wiki (存档
- XFS FAQ
- 通过减少日志开销来提高元数据性能
- XFS Wikipedia 条目
- XFS 用户指南 XFS 用户指南不再存在,但有一个指向 git 仓库的链接