背景
在一次断电过了几个小时之后,实验室集群的文件夹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/sdb1为xfs的文件格式。考虑用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 cleaningGoogle查阅出现该错误的原因,大部分提示使用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 会丢弃日志,强制修复(可能导致最近未同步的元数据丢失)。
修复后验证
挂载:
mount /dev/sdb1 /mnt/test检查:
dmesg | tail
xfs_info /mnt/test
xfs_check /dev/sdb1 # 可选,已弃用但仍可用于快速校验查看
/lost+found:
ls -lh /mnt/test/lost+found这里会放修复过程中找回但无目录引用的文件。
xfs_repair 修复阶段(内部流程)
了解阶段有助于读懂日志输出:
运行时可以看到类似:
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