XFS根分区无法挂载的解决办法

最近线上碰到的一个XFS根分区无法挂载导致无法开机的问题
因为系统无法开机,首先想到的是先把系统启起来,所以打算从管理口挂载光盘,从光盘启动:

启动后选择“1”,将文件系统挂载到/mnt/sysimage

执行

# chroot /mnt/sysimage

根分区一直处于挂载中,但始终挂载不上去,挂载进程处于D僵死状态,无法杀死,看了一下进程的调用栈,一直处于xfs_buf_iowait()函数中,其调用关系为xfs_buf_iowait() <- xfs_buf_read(),看了一下xfs_buf_iowait()的代码感觉是一直在等待completion信号量:

# fs/xfs/xfs_buf.c
xfs_buf_iowait(xfs_buf_t *bp)
 {
         trace_xfs_buf_iowait(bp, _RET_IP_);
         wait_for_completion(&bp->b_iowait);
         trace_xfs_buf_iowait_done(bp, _RET_IP_);
         return bp->b_error;
}

希望用xfs_info查看一下根分区元数据是否损坏,结果xfs_info相关的进程也进入了D状态,mount进程处于D僵死状态,无法杀死xfs_check/xfs_repair需要在umount的情况下执行,所以此路不通。

# xfs_info /dev/mapper/centos-root

观察这个进程的调用栈,发现基本是停在了
rwsem_acquire_read() <- down_read() <- get_super(),怀疑是获得读写锁失败了,因为已经被mount进程给占用,一直在等待锁的释放。

后来想着能不能不挂载根分区,果然光盘的救援模式提供了不挂载根分区的选项:
这里我们选择3)Skip to shell,直接进入系统后,
因为根分区/dev/mapper/centos-root对应的实际时/dev/dm-0,所以我们可以通过xfs_check/xfs_repair来检查一下,-n是指仅检查不修复:

# xfs_repair -n /dev/dm-0


可以看到我们的元数据还在,但是日志和数据不一致,xfs默认会在挂载的时候修复这种不一致,操作系统给出的建议是以读写的方式挂载并自动修复,我们先尝试以只读不修复方式挂载文件系统,然后再试试以读写方式挂载并修复:

# mount -o ro,norecovery /dev/dm-0 /data0

文件系统成功以只读方式挂载,内容还在。

后来,又尝试以读写方式挂载,发现挂载进程D状态偶尔会变成R状态,原来并不是真正的僵死了,大概等了3个小时,终于挂载并同步成功了,算是万幸。

如果万一挂载不成功,可以进一步执行以下操作,清除日志再挂载:

# xfs_reapir -L /dev/dm-0

这是一步有风险的操作,在执行之前最好先使用xfs_dump、xfs_restore备份你的分区,既可以备份成一个文件也可以备份到另一块硬盘:

  1. 备份成一个文件
    以只读方式挂载待备份的根分区:

    # mount -o ro,norecovery /dev/dm-0 /data0
    
    # xfsdump -f /tmp/data_dump /data0 -L data_dump -M data_dump
    
  2. 备份到硬盘
    以只读方式挂载待备份的根分区:

    # mount -o ro,norecovery /dev/dm-0 /data0
    

    新建一个备份分区,xfs方式挂载到/data1:

    # mkfs.xfs /dev/sdb1
    

    再将需要备份的xfs文件系统/data0备份到/data1备份盘:

    # xfsdump - /data0 | xfsrestore - /data1
    

接下来就可以瞎折腾了。。。

恢复可执行:

    # xfsrestore -f /tmp/data_dump /data0
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页