使用 dd 在 XFS 文件系统中截断文件 - 如何恢复

Truncated file in XFS filesystem using dd - how to recover

磁盘布局 我的 HDD raid 阵列快要报废了,我为此买了一些新磁盘。 我曾将旧硬盘用作 kvm/qemu 虚拟机的原始磁盘映像存储。 Raid 阵列是使用 mdadm 构建的。在 md 设备上,我有 LVM 的物理卷。在物理卷上,我有存储原始磁盘映像的 XFS 文件系统。 每个原始磁盘映像都是由 qemu-img 制作的,并包含 LVM 的物理卷。一个 PV = 一个 LV = 一个原始磁盘映像中的 VG。

动作 当我尝试使用 cp 进行数据移动时,我在我的 raid 阵列中遇到了坏块和 i/o 问题,所以我从 cp 切换到 dd with noerror,sync flags 我写了dd if=/mnt/old/file.img of=/mnt/**old**/file.img bs=4k conv=noerror,sync

问题 现在文件 /mnt/old/file.img 在 XFS 文件系统中的大小为零。 有没有简单的解决方案来恢复它?

我的感觉是您的 RAID 阵列出现故障。您可以通过...查看 RAID 状态...

 cat /proc/mdstat

由于您看到 i/o 个错误,这很可能是您问题的根源。前进的最佳途径是制作每个 RAID 成员的扇区级副本(或至少是抛出 i/o 错误的成员)。参见 Linux ddrescue。它旨在复制故障硬盘。然后从副本执行恢复工作。

终于找到解决办法了,但是不是很简单

Xfs_undelete 没有匹配我的问题,因为它不支持非常大的文件的 B+Tree 扩展存储格式 (V3)。

成功 semi-manual 解决我的问题的过程包括以下主要步骤:

  1. 立即卸载文件系统并使用 dd 对文件进行完整分区备份
  2. 调查有关截断文件的 XFS 日志条目
  3. 在专家模式下使用 xfs_db 手动还原 inode 核心 header MB。恢复 inode 核心不会取消标记为 non-free,并且当您尝试以通常方式从具有已恢复 inode header 的文件中复制一些数据时,您将收到 i/o 错误。 这是开发 python 脚本的原因。
  4. 使用脚本从 B+Tree 树中提取 extents 数据作为 inode 并将它们写入磁盘

我已根据 LGPL 许可在 GitHub

发布了恢复脚本

P.S。由于损坏的 inode b+tree extent 记录,一些数据丢失了,但它们对我来说没有意义。