XFS 文件系统运维:碎片、配额与在线修复实战

RHEL/CentOS 7 之后 XFS 成了默认文件系统,跑数据库、虚拟化镜像、日志盘的机器上几乎都是它。但 XFS 的运维方法和 ext4 差别很大:没有 e2fsck 那套流程,碎片整理、配额管理、在线修复各有各的工具,照 ext4 的经验操作很容易踩坑。本文只讲生产中最常用的四件事:日常巡检、碎片整理、配额管理与损坏修复。

先说一条铁律:xfs_repair 只能在文件系统卸载后运行,挂载状态下跑会进一步损坏数据。根分区出问题需要进救援模式或 LiveCD 处理,不要抱侥幸心理在线修。

一、日常巡检:先看空间、再看 inode、最后看碎片

XFS 磁盘满有三种形态:数据空间满、inode 耗尽、元数据区异常。只看 df -h 会漏掉后两种。巡检固定看四项:空间、inode、碎片度、日志状态。

# 空间与 inode
df -hT /data
df -i /data
# 碎片度:extents 碎片比例,超过 10% 值得关注
xfs_db -r -c 'frag' -c 'freesp -s' /dev/sdb1
# 文件系统健康与日志
xfs_info /data
xfs_logprint -t /dev/sdb1 2>&1 | tail -20
# 找出占空间的大文件与大目录
du -sh /data/* 2>/dev/null | sort -rh | head -10

XFS 的 inode 是动态分配的,一般不会像 ext4 那样出现“空间还剩很多、inode 先用完”的情况,但小文件海量场景下仍要看 df -i。碎片度 frag 输出的是文件碎片比例,数据库与虚拟机镜像盘碎片高了会直接反映在随机读延迟上。

二、碎片整理:xfs_fsr 的影响评估与执行

XFS 的碎片整理工具是 xfs_fsr,它会重组文件的数据块布局。关键点:它是按文件逐个整理的,在线执行、不用卸载,但整理期间会产生额外的磁盘 I/O,大文件整理时 I/O 争抢明显,务必放在业务低峰期跑,并先评估收益。

# 只看碎片最严重的前 10 个文件,不直接整理
xfs_db -r -c 'frag' /dev/sdb1
# 对单个大文件整理(先评估再动手)
xfs_fsr -v /data/vm-images/disk.qcow2
# 全盘整理:低峰期跑,-t 限制每次运行时间(秒),避免拖垮业务
xfs_fsr -t 3600 /data
# 整理后复查碎片度
xfs_db -r -c 'frag' /dev/sdb1

不是所有文件都值得整理:只写一次、很少再读的冷数据整理了也没收益;频繁追加写的日志文件整理后很快又会碎。优先整理虚拟机镜像、数据库数据文件这类随机读多的大文件。

三、配额管理:项目配额与用户配额的落地方式

XFS 支持用户、组与项目(project)三级配额,共享目录按项目限额是最常用的场景:给每个业务目录划一个项目 ID,限制它的总容量,超了就报磁盘满、不会拖垮整盘。开启配额需要挂载参数,改完要重新挂载。

# 挂载时开启项目配额(/etc/fstab 示例)
# /dev/sdb1  /data  xfs  defaults,prjquota  0 0
mount -o remount,prjquota /data
# 给业务目录划项目:项目 ID 100,目录 /data/project-a
echo '100:/data/project-a' >> /etc/projects
echo 'project-a:100' >> /etc/projid
xfs_quota -x -c 'project -s project-a' /data
# 限额 500G,软限 450G(超软限开始告警,超硬限直接拒绝写入)
xfs_quota -x -c 'limit -p bsoft=450G bhard=500G project-a' /data
# 查看用量与超限情况
xfs_quota -x -c 'report -p -h' /data
xfs_quota -x -c 'df -h' /data

注意:配额统计的是文件实际占用的块,稀疏文件的空洞不计入;删除文件后配额立即释放。用户配额与组配额的命令类似,把 -p 换成 -u/-g 即可。

四、在线扩容:扩容前必须确认的三个前提

XFS 支持在线扩容,不用卸载、不用停业务,这是它相对 ext4 的大优势。但扩容前必须确认三件事:底层卷(LVM 或云盘)已经扩容、文件系统当前健康、扩容后有回退预案。顺序错了,扩容命令会直接报错。

# 1. 确认底层已扩:LVM 先扩 LV,云盘先在控制台扩容再 rescan
pvdisplay /dev/sdb | grep -E 'PV Size|Free'
lvextend -L +100G /dev/mapper/vgdata-lvdata
# 2. 确认文件系统健康(只读检查)
xfs_db -r -c 'sb 0' -c 'p' /dev/mapper/vgdata-lvdata | head -20
# 3. 在线扩容到 LV 的全部可用空间
xfs_growfs /data
df -hT /data
# 指定扩到固定大小(单位为数据块数,需先算好)
xfs_growfs -D 26214400 /data

XFS 只支持扩容、不支持缩容,扩之前先算好容量规划,扩大了收不回来。云盘扩容后若 xfs_growfs 提示大小没变,先检查 lsblk 是否已看到新容量,没看到是 rescan 没做,不是文件系统的问题。

五、损坏修复:xfs_repair 的标准流程与常见报错

XFS 元数据损坏的典型征兆:挂载失败报 Structure needs cleaning、ls 某个目录报 Input/output error、dmesg 出现 XFS 错误。修复流程固定:先备份元数据镜像,再卸载,再修复,最后验证。

# 1. 先备份元数据(出问题还能找厂商或二次修复)
xfs_metadump /dev/sdb1 /tmp/sdb1-metadump.img
# 2. 卸载(卸载不掉先查谁在占用)
umount /data || fuser -mv /data
# 3. 先干跑,看损坏范围,不实际修改
xfs_repair -n /dev/sdb1
# 4. 正式修复;日志损坏严重时才加 -L(会清空日志,可能丢最近写入)
xfs_repair /dev/sdb1
# 5. 修复后挂载并验证,重点看之前报错的目录
mount /data
ls -l /data | head
dmesg -T | grep -i xfs | tail -20

-L 参数要慎用:它会丢弃日志里未回放的元数据变更,可能导致最近写入的文件丢失,只在普通修复报“日志损坏无法修复”时才用。修复后若个别文件进了 lost+found,按 inode 号与业务方逐个确认归属,不要批量删除。

六、挂载选项与日志参数:按负载选,别照抄模板

XFS 的挂载选项直接决定写入行为:日志大小与刷盘策略影响元数据密集型负载,大文件顺序写则更看重分配策略。默认挂载选项对通用场景够用,但数据库、对象存储这类有明确 I/O 特征的业务,值得按负载调一调。改挂载选项要先在测试盘上验证,改错选项可能导致挂载失败,生产操作务必先备份 fstab。

# 看当前文件系统的实际参数(比猜配置可靠)
xfs_info /data
# 查看当前挂载选项
findmnt -o TARGET,SOURCE,FSTYPE,OPTIONS /data
# 常见调优组合(写进 /etc/fstab,改前先备份):
# /dev/sdb1 /data xfs defaults,noatime,nodiratime,logbufs=8,logbsize=256k 0 0
# noatime:不更新访问时间,减少元数据写,读多场景收益明显
# logbufs/logbsize:加大日志缓冲,元数据密集型写入更稳
# allocsize=64m:大文件预分配,减少碎片(对象存储、大文件写入场景)
# inode64:大容量盘上避免 inode 号溢出问题
# 改完重新挂载验证
mount -o remount /data && findmnt /data

注意两个误区:一是 discard(在线 TRIM)不要在所有 SSD 上都开,频繁 TRIM 会拖慢写入,定期用 fstrim 更稳;二是日志参数不是越大越好,logbsize 过大会占用过多内存,小文件系统上反而浪费。调完用实际业务负载压测,看写入延迟与碎片率的变化再定。

七、大文件写入与碎片:延迟分配的另一面

XFS 的延迟分配会把小写入合并成大块顺序写,对吞吐友好,但也会让“空间还够却写不进”的问题更难定位:多个进程同时写大文件时,预留空间可能超出实际可用空间,写到一半才报 ENOSPC。排查时要看实际分配情况,而不是只看 df 的剩余空间。

# 看单个文件的实际分配块与空洞(判断是否碎片严重)
xfs_bmap -v /data/bigfile.bin | head -30
# 看文件系统整体碎片程度
xfs_db -r -c "freesp -s" /dev/sdb1
# 看延迟分配与预留空间占用
cat /proc/fs/xfs/stat | grep -i alloc
# 大文件写入场景:用 fallocate 预分配,避免写到一半空间不足
fallocate -l 10G /data/prealloc.bin
# 批量删除大文件后,空间不释放先查未关闭句柄
lsof +L1 /data | head -20

碎片严重的典型信号是顺序读速度明显下降、xfs_bmap 显示一个文件被切成上千个 extent。这时先评估 xfs_fsr 的影响再动手整理,不要在业务高峰期跑。预防比治理重要:大文件写入尽量用预分配或固定块大小写,避免多个小写入交错进同一个文件。

八、冻结快照备份:xfs_freeze 的正确用法

做文件系统级备份时,直接拷正在写入的卷可能拿到不一致的数据。xfs_freeze 可以把文件系统冻结在一致状态,配合 LVM 快照或存储快照,就能拿到可恢复的备份点。冻结期间所有写入都会阻塞,所以操作要快,冻结、快照、解冻要写成一个脚本,不要手动分步执行。

# 冻结 + LVM 快照 + 解冻,一气呵成(超时要设好,避免冻结过久)
xfs_freeze -f /data
lvcreate -L 10G -s -n data-snap /dev/vg0/data
xfs_freeze -u /data
# 挂载快照做备份(只读挂载,避免误写)
mount -o ro,nouuid /dev/vg0/data-snap /mnt/snap
tar -czf /backup/data-$(date +%F).tar.gz -C /mnt/snap .
# 备份完卸载并删除快照
umount /mnt/snap
lvremove -f /dev/vg0/data-snap
# 检查快照期间有没有写满(快照空间耗尽会导致快照失效)
lvs -o lv_name,lv_size,data_percent /dev/vg0/data-snap

快照空间要按冻结期间的写入量来估,写得多就给大一点,低于 20% 剩余就告警。数据库文件不要只靠文件系统快照恢复,数据库自身的备份机制才是主恢复路径,快照只作为补充。演练时要实际从快照恢复一次,确认备份文件能解开、业务能认出来。

九、避坑清单

  • 不要在挂载状态下跑 xfs_repair;不要对根分区在线修复,进救援模式处理。
  • 不要用 fsck.xfs 指望它修东西:它只是个空壳,真正修复靠 xfs_repair。
  • 大文件删除后空间不释放,先查有没有进程还握着句柄(lsof | grep deleted),再怀疑文件系统。
  • 配额与扩容操作前,先在测试盘上完整走一遍流程,生产盘只执行验证过的命令。
  • 元数据备份 xfs_metadump 要定期做,它是修复失败后最后的兜底材料。

发表回复

后才能评论