读取错误恢复mdadm + lvm + ext4分区

我的NAS中的一个磁盘失败了。 NAS正在运行Linux,并将mdadm + LVM技术用于其文件系统。

我对大部分内容都有备份,但是对于最后的更改没有备份,如果可能的话,我想从这个故障磁盘中恢复。

磁盘(一个“绿色驱动器”WD10EARS 1TB大小)抛出这种错误:

Oct 3 12:00:41 kernel: [ 3625.620000] ata5.00: read unc at 9453282 Oct 3 12:00:41 kernel: [ 3625.620000] lba 9453282 start 9453280 end 1953511007 Oct 3 12:00:41 kernel: [ 3625.620000] sde5 auto_remap 0 Oct 3 12:00:41 kernel: [ 3625.630000] ata5.00: exception Emask 0x0 SAct 0x1 SErr 0x0 action 0x6 Oct 3 12:00:41 kernel: [ 3625.630000] ata5.00: edma_err_cause=00000084 pp_flags=00000003, dev error, EDMA self-disable Oct 3 12:00:41 kernel: [ 3625.640000] ata5.00: failed command: READ FPDMA QUEUED Oct 3 12:00:41 kernel: [ 3625.650000] ata5.00: cmd 60/40:00:e0:3e:90/00:00:00:00:00/40 tag 0 ncq 32768 in Oct 3 12:00:41 kernel: [ 3625.650000] res 41/40:00:e2:3e:90/12:00:00:00:00/40 Emask 0x409 (media error) <F> Oct 3 12:00:41 kernel: [ 3625.660000] ata5.00: status: { DRDY ERR } 

然而,在用“dd”进行testing时,我注意到如果我跳过第一个4kB,读取似乎是可以的,也就是类似的命令。 dd if = / dev / sde5 of = dev / null bs = 4k count = 1000 skip = 1不返回任何读取错误。

假设在磁盘的其余部分没有其他的读取失败,我能否恢复这个900 GB的分区(就像我之前提到的那样,它是一个'linux raid autodetect'分区,它包含一个LVM2卷,其中包含一个ext4文件系统)如果我复制克隆到其他地方的分区,但第一个4kB?

否则(即如果你已经有退化arrays),你仍然应该能够做到这一点。

如果你的mdadm创build的数组是<v.3.0,那么有效负载从偏移量0x22000开始(如果是v.3.0或更高版本,则进一步向上),这也是在删除第一个4KB之前。

所以只有linux-raid超级块被损坏了,但是这并不难恢复(特别是如果你的数组中的其他设备是完好的)。

考虑到这是一个相对简单的情况,一个md设备作为一个线性分配的LVM卷的单一物理设备工作,并包装一个ext4 fs,我的解决scheme是直接在ext4 fs之后,并将其挂载为一个循环文件​​系统恢复所需的时间。

我的步骤:

  • 如上所述,用dd我把整个损坏的分区复制到一个健康的磁盘上的一个类似大小的分区(这里下面命名为/ dev / sdd5
  • 我将/ dev / sdd5的第一个MB复制到一个文件中,并导入到我的Ubuntu桌面计算机,在这里我用hex编辑器ghex打开它
  • 我从ext wiki https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#The_Super_Block看到,EXT4超级块在0x38的偏移量处有魔法数字0xEF53,从我的hex转储中我可以find这个签名&#x3002;
  • 用一个不同的,健康的ext4文件系统重做,我发现超级块的开始在分区开始之后是1024个字节,所以我计算了从分区sdd5开始到我寻找的ext4分区开始的偏移量。
  • 我用losetup -o <offset> /dev/loop0 /dev/sdd5创build了循环分区
  • fsck -n /dev/loop0 ,偏移是正确的,因为我确实得到了一个有效的分机fs,文件系统至less处于一致的状态。
  • 我将环路fs以只读模式mount -o ro /dev/loop0 /tmp/recovery到一个临时目录: mount -o ro /dev/loop0 /tmp/recovery

在这一点上,我可以开始访问我想从/ tmp / recovery /中恢复的内容。