我有一个 Synology 扩展 (DX213) 连接到我的 NAS。它装有 2 个 2TB 的磁盘,它们处于 RAID0 配置中(糟糕的想法,我知道,我不需要提醒 ;) )。上周末,阵列发生故障,我无法再启动 RAID 阵列。
我开始相信问题出在背板(DX213)而不是磁盘上,因为它们看起来没问题。它们肯定还没有坏掉(目前还没有)。我将它们连接到 Linux 机器上,我可以清楚地看到它们:
$ sudo fdisk -l /dev/sdb
Disk /dev/sdb: 1.8 TiB, 2000396746752 bytes, 3907024896 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x000a85dd
Device Boot Start End Sectors Size Id Type
/dev/sdb1 256 4980735 4980480 2.4G 83 Linux
/dev/sdb2 4980736 9175039 4194304 2G 82 Linux swap / Solaris
/dev/sdb3 9437184 3907024064 3897586881 1.8T 83 Linux
$ sudo fdisk -l /dev/sdc
Disk /dev/sdc: 1.8 TiB, 2000396746752 bytes, 3907024896 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x0004dd4e
Device Boot Start End Sectors Size Id Type
/dev/sdc1 256 4980735 4980480 2.4G 83 Linux
/dev/sdc2 4980736 9175039 4194304 2G 82 Linux swap / Solaris
/dev/sdc3 9437184 3907024064 3897586881 1.8T 83 Linux
检查磁盘时,mdadm
仍然可以识别 raid 阵列,并且两个磁盘似乎都处于干净状态,但两个磁盘上的超级块明显不同步。
$ sudo mdadm --examine /dev/sd[bc]3
/dev/sdb3:
Magic : a92b4efc
Version : 1.2
Feature Map : 0x0
Array UUID : 1d7dd58f:dd7dd3d2:b646173b:afd51417
Name : mist-nas:2
Creation Time : Tue Nov 26 19:47:24 2013
Raid Level : raid0
Raid Devices : 2
Avail Dev Size : 3897584833 (1858.51 GiB 1995.56 GB)
Data Offset : 2048 sectors
Super Offset : 8 sectors
Unused Space : before=1968 sectors, after=0 sectors
State : clean
Device UUID : 46933df7:36901a5b:7a1239fe:e999c419
Update Time : Sat Aug 27 20:14:12 2016
Checksum : 42117b5b - correct
Events : 8
Chunk Size : 64K
Device Role : Active device 0
Array State : A. ('A' == active, '.' == missing, 'R' == replacing)
/dev/sdc3:
Magic : a92b4efc
Version : 1.2
Feature Map : 0x0
Array UUID : 1d7dd58f:dd7dd3d2:b646173b:afd51417
Name : mist-nas:2
Creation Time : Tue Nov 26 19:47:24 2013
Raid Level : raid0
Raid Devices : 2
Avail Dev Size : 3897584833 (1858.51 GiB 1995.56 GB)
Data Offset : 2048 sectors
Super Offset : 8 sectors
Unused Space : before=1968 sectors, after=0 sectors
State : clean
Device UUID : e4b60f4c:604b2e27:359cb71b:24453937
Update Time : Tue Nov 26 19:47:24 2013
Checksum : 997fa41a - correct
Events : 4
Chunk Size : 64K
Device Role : Active device 1
Array State : AA ('A' == active, '.' == missing, 'R' == replacing)
唯一的区别是最后更新时间戳和事件计数。我知道阵列发生故障时没有正在进行写入操作,并且两个磁盘都处于干净状态,因此我非常有信心我仍然可以访问我的数据。但是要恢复,我必须重新创建阵列或摆弄有故障的超级块,这至少让我感到毛骨悚然……
我已经将两个驱动器克隆到dd
新驱动器上,以便在我做傻事时有备份。新驱动器的扇区大小为 4096(它们是 3 和 4TB 磁盘),而旧驱动器的扇区大小为 512。sd[bc]3 分区的大小不是 4096 个扇区的倍数,所以我不得不将分区的大小四舍五入到下一个扇区。我希望这不是问题?
我正在考虑运行的命令是:
$ sudo mdadm --create --readonly --assume-clean --level=0 -n2 /dev/md2 /dev/sdb3 /dev/sdc3
此命令可能会覆盖当前的超级块,因此我想绝对确保这不会破坏我恢复数据的机会。此命令的结果是什么?
在真正行动之前,我还想验证一下我的策略。我在 USB 密钥上创建了 2 个 4GB 分区,用它们创建了一个 RAID0 阵列,在阵列上创建了一个 EXT4 文件系统,挂载了它并在其中复制了一些文件。问题是我如何操作其中一个分区的超级块来重现我在 4TB 阵列中遇到的情况。
我考虑使用十六进制编辑器手动操作超级块,但这样可能还需要重新计算校验和。我该怎么做?
答案1
您应该从阵列中移除驱动器,将其从系统中移除,重新探测磁盘,然后将驱动器重新添加到阵列中。
使用以下命令从阵列中删除故障驱动器
mdadm --manage --set-faulty
物理地从系统中移除/重新插入驱动器(或使用设备删除和 scsi 主机重新扫描)。
现在检查是否再次找到驱动器,并检查它是否正常工作。您可以查看 dmesg 输出或查看 /proc/partitions。pv <
在设备上运行。
然后使用 将驱动器重新添加到阵列mdadm
。
然后进行最后检查,cat /proc/mdstat
看看是否成功。
答案2
我设法找回了我的数据,尽管方法并不简单(剧透:它包括十六进制编辑器和一些逆向工程)。我只是发布我的方法以供将来参考。
因此,我的 RAID0 阵列因超级块不匹配而损坏。由于 RAID0 中没有冗余,因此mdadm
除非所有超级块都匹配,否则无法启动 RAID0 阵列。我的磁盘看起来不错,但超级块不同步。
解决方案:使超级块再次匹配。
第一个想法:运行上述命令,将完全按照之前的方式重新创建 RAID 阵列,但会覆盖当前的超级块。
评估的第一个想法:有风险。无法保证mdadm
会以与以前完全相同的方式重新创建阵列。也许我会忘记一些参数,也许mdadm
会写入我想要的其他地方,从而破坏我的底层文件系统和数据,甚至其他东西。
结论:坏主意。
第二个想法。使用十六进制编辑器自己操作超级块。
优点:
- 我能控制一切,除非我犯了愚蠢的错误,否则不会对无关紧要的字节进行任何更改。
- 只有超级块的不匹配值才会被修改,因此数组的布局不会受到影响。
挑战:
- 超级块写在磁盘的什么位置?
- 它看起来怎样?
mdadm --examine
我能否识别正确的字节并通过读取十六进制值重建输出?- 更改属性将使超级块校验和无效,如何获得有效的校验和?
事实证明,这些挑战很容易克服。linux-raid wiki 上有一个很棒的页面:https://raid.wiki.kernel.org/index.php/RAID_superblock_formats。它记录了 v1 超级块以及在磁盘上找到它的位置。对于 v1.2 超级块,它位于磁盘开头 4K 处,并写入下一个 4K(因为它是扇区对齐的,新磁盘使用 4K 扇区,即使使用它的磁盘有 512 字节扇区)。
您还可以参考 v1 超级块的源代码,它并不太难阅读:https://github.com/neilbrown/mdadm/blob/master/super1.c
经过仔细的分析,我确定了这个计划:
首先,备份每个磁盘的前 8K。这样我就可以随时恢复到原始状态。
dd if=/dev/sdXY of=sdXY.backup bs=1 count=8K
提取每个磁盘的超级块。这很容易做到
dd if=/dev/sdXY of=sdXY.superblock bs=1 count=4K skip=4K
在十六进制编辑器中读取超级块。我发现基于网络的http://hexed.it非常好。
修改必要的属性,保留校验和。修改时间戳时要小心。Linux 时间戳占用 32 位或 4 个字节,Linux
mdadm
时间戳占用 64 位或 8 个字节。不要忘记复制其他 4 个。超级块为 256 个字节 + 数组每个成员的 2 个字节。这些最后的字节是成员 ID 或角色的序列。将超级块写入磁盘。
dd if=sdXY.superblock of=/dev/sdXY bs=1 count=4K seek=4K
使用 检查超级块
mdadm --examine /dev/sdXY
。它将向您显示校验和无效,但也会向您显示预期的校验和。将校验和修改为正确的值。在十六进制编辑器中,字节被反转,因此
becomes
十六进制编辑器中为“99 7F A4 1A 1A A4 7F 99”。使用与步骤5相同的命令将新的超级块写入磁盘。
对每个磁盘重复此操作。
当两个超级块匹配时,我就可以再次启动阵列了。我检查了文件系统,发现它看起来是干净的。挂载文件系统并将所有内容复制到 RAID5 阵列,我很快也会用 UPS 保护它。
我很幸运,不会忘记这些非常可怕的时刻。我一直保持冷静,不断思考如何重新组装阵列。
我强烈建议在彻底分析问题之前不要摆弄损坏的阵列。另外,我在开始之前写下了我的计划,这样我就不会跳过任何一步,导致数据丢失的风险。