Administrator
发布于 2025-10-22 / 10 阅读
0
0

linux服务器xfs文件系统因断电出现input_output error错误的修复过程

背景

在一次断电过了几个小时之后,实验室集群的文件夹ls时候,出现了input/output error。集群是使用两台存储节点通过NFS来与各个计算节点共享文件夹。在计算节点的文件夹读取出现了input/output error错误,怀疑存储节点io02的硬盘发生了问题。ssh登陆到储存节点io02,发现同样出现了input/output error,之后通过重启存储节点io02,在计算节点上重新使用NFS挂载文件夹的命令挂载文件后,文件夹重新恢复,这个时候需要实验室同学提醒备份文件夹,硬盘出问题了。但是过了几个小时,又是出现错误。最后一次,直接发现整个文件夹已经不存在,因此需要修复一下。

排查

首先是ssh到出问题的存储节点io02的服务器,下面大部分命令需要使用root权限才能执行。

查看提醒信息

重启开机之后,机子有下面的错误:

Message from syslogd@io02 at Nov 27 14:26:44 ...
 kernel:BUG: soft lockup - CPU#1 stuck for 67s! [xfsbufd/sdb1:2914]

初步怀疑为硬盘出错,导致内核软锁定。

查看/var/log/messages信息,辅助排查

$less +GG /var/log/message

摘取部分信息:

Nov 27 14:40:29 io02 abrtd: Email was sent to: root@localhost
Nov 27 14:40:29 io02 abrtd: Duplicate: UUID
Nov 27 14:40:29 io02 abrtd: DUP_OF_DIR: /var/spool/abrt/oops-2018-11-27-14:25:21-2777-0
Nov 27 14:40:29 io02 abrtd: Problem directory is a duplicate of /var/spool/abrt/oops-2018-11-27-14:25:21-2777-0
Nov 27 14:40:29 io02 abrtd: Deleting problem directory oops-2018-11-27-14:39:21-2777-0 (dup of oops-2018-11-27-14:25:21-2777-
0)
Nov 27 14:40:29 io02 abrtd: Can't open file '/var/spool/abrt/oops-2018-11-27-14:25:21-2777-0/uid': No such file or directory
Nov 27 14:40:44 io02 kernel: BUG: soft lockup - CPU#1 stuck for 67s! [xfsbufd/sdb1:2914]
Nov 27 14:40:44 io02 kernel: Modules linked in: bridge xfs nfsd lockd nfs_acl auth_rpcgss exportfs autofs4 sunrpc target_core

发现有Duplicate: UUID的错误,先跳过往后继续查。

查看dmesg信息,辅助排查

#dmesg | tail

这些摘取关键的信息:

XFS (sdb1): xfs_do_force_shutdown(0x8) called from line 3863 of file fs/xfs/xfs_bmap.c.  Return address = 0xffffffffa04fb4e6
XFS (sdb1): Corruption of in-memory data detected.  Shutting down filesystem
XFS (sdb1): Please umount the filesystem and rectify the problem(s)
...
XFS (sdb1): xfs_log_force: error 5 returned.
XFS (sdb1): xfs_log_force: error 5 returned.

在查看了部分信息之后,可以肯定是sdb1这个分区的文件系统出了问题,下面可以针对sdb1进行排查

查看分区文件类型

#blkid

会列出分区的信息,类型等。下面为/dev/sdb1的信息

/dev/sdb1: UUID="6c688386-8f03-4f63-a60d-66a6c59777d9" TYPE="xfs"

发现主要的数据分区/dev/sdb1xfs的文件格式。考虑用xfs文件系统的相关修复命令。

查看挂载信息

#df -h

发现只有下面的信息:

Filesystem            Size  Used Avail Use% Mounted on
/dev/sda3             764G   20G  705G   3% /
tmpfs                 7.8G     0  7.8G   0% /dev/shm
/dev/sda1              97M   59M   33M  65% /boot

说明主要的数据分区/dev/sdb1因为出了状况,没有被挂载上。

查看硬盘分区信息

#fdisk -l

得到下面的硬盘分区信息。

Disk /dev/sda: 899.8 GB, 899785162752 bytes
255 heads, 63 sectors/track, 109392 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00053bbc

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1          13      102400   83  Linux
Partition 1 does not end on cylinder boundary.
/dev/sda2              13        8172    65536000   82  Linux swap / Solaris
/dev/sda3            8172      109393   813057024   83  Linux

WARNING: GPT (GUID Partition Table) detected on '/dev/sdb'! The util fdisk doesn't support GPT. Use GNU Parted.


Disk /dev/sdb: 8997.9 GB, 8997945999360 bytes
255 heads, 63 sectors/track, 1093937 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               1      267350  2147483647+  ee  GPT

上面中显示Disk /dev/sdb: 8997.9 GB, 8997945999360 bytes中为接近9T的容量,在/dev/sdb1这个分区,这个分区就是存储数据的分区,是做了磁盘阵列的。既然这个分区没有被挂载,那就挂载下这个分区。

挂载分区

#mount /dev/sdb1 /data

出现错误提示:

failed: Structure needs cleaning

Google查阅出现该错误的原因,大部分提示使用xfs_pair来进行修复。综合上面的错误信息,也应该知道,是需要对xfs文件系统进行修复了。

使用xfs_repair对文件系统进行修复

使用xfs_repair之前,要先卸载该文件系统(分区),因为/dev/sdb1分区已经卸载的了。因此下面可以直接进行。

使用xfs_metadump保存元数据信息

xfs_metadump -o /dev/sdb1 /save/sdb1.metadump

这步只是对元数据进行了保存,保存在了/save/sdb1.metadump这个文件,没有对数据进行备份,因为如果要备份数据本身的话,需要和数据一样大小的空间,显然这里没有这个空间。

如果磁盘足够大,也可以直接做镜像:

dd if=/dev/sdb1 of=/root/sdb1.img bs=64M status=progress

尝试只读挂载(非破坏性检查)

有时候只是日志未 replay:

mount -o ro /dev/sdb1 /mnt/test

如果能挂载成功,说明结构大体正常。

这时执行:

xfs_repair -n /dev/sdb1

-n 表示 只检查、不修改(dry-run)

输出会显示类似:

Phase 1 - find and verify superblock...
Phase 2 - using internal log
...
would clear log
would rebuild AG headers

看到 “would” 表示不会实际操作。

正式修复

xfs_repair /dev/sdb1

如果出现日志损坏,提示:

XFS: log inconsistent (dirty log)

可以使用:

xfs_repair -L /dev/sdb1

⚠️ -L丢弃日志,强制修复(可能导致最近未同步的元数据丢失)。

修复后验证

  1. 挂载:

mount /dev/sdb1 /mnt/test
  1. 检查:

dmesg | tail
xfs_info /mnt/test
xfs_check /dev/sdb1  # 可选,已弃用但仍可用于快速校验
  1. 查看 /lost+found

ls -lh /mnt/test/lost+found

这里会放修复过程中找回但无目录引用的文件。

xfs_repair 修复阶段(内部流程)

了解阶段有助于读懂日志输出:

阶段

操作内容

Phase 1

查找并验证超级块(superblock)

Phase 2

扫描 inode B+Tree,校验 inode 完整性

Phase 3

校验目录结构(目录项指向正确 inode)

Phase 4

校验并重建文件数据块索引

Phase 5

校验空闲空间索引(free space B+Tree)

Phase 6

修复配额(quota)信息

Phase 7

更新超级块并写回磁盘

运行时可以看到类似:

Phase 1 - find and verify superblock...
Phase 2 - using internal log
Phase 3 - verify ...
Phase 4 - rebuilding AGF trees...
Phase 5 - check free space...
Phase 6 - check quota...
Phase 7 - write out repaired metadata

典型问题及处理建议

报错信息

原因

修复方式

metadata corruption detected

元数据不一致

xfs_repair /dev/sdX

dirty log / log recovery failed

日志损坏

xfs_repair -L /dev/sdX

bad primary superblock

超级块坏

xfs_repair -o sb=<sector> /dev/sdX

cannot open device

挂载中或 busy

umount 后再修

I/O error

硬盘坏块

先用 smartctl / badblocks 检查


评论