我在zpool中有几TB非常有价值的个人数据,由于数据损坏,我无法访问这些数据。该池最初是在2009年左右在FreeBSD 7.2系统上建立的,该系统在Ubuntu 8.04系统顶部的VMWare虚拟机中运行。FreeBSD VM仍然可用并且运行良好,现在只有主机OS已更改为Debian6。来宾VM可以通过VMWare通用SCSI设备访问硬盘,共有12个。
有2个游泳池:
- zpool01:2x 4x 500GB
- zpool02:1x 4x 160GB
工作的是空的,坏掉的保留所有重要数据:
[user@host~]$ uname -a
FreeBSD host.domain 7.2-RELEASE FreeBSD 7.2-RELEASE #0: \
Fri May 1 07:18:07 UTC 2009 \
root@driscoll.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC amd64
[user@host ~]$ dmesg | grep ZFS
WARNING: ZFS is considered to be an experimental feature in FreeBSD.
ZFS filesystem version 6
ZFS storage pool version 6
[user@host ~]$ sudo zpool status
pool: zpool01
state: UNAVAIL
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
zpool01 UNAVAIL 0 0 0 insufficient replicas
raidz1 UNAVAIL 0 0 0 corrupted data
da5 ONLINE 0 0 0
da6 ONLINE 0 0 0
da7 ONLINE 0 0 0
da8 ONLINE 0 0 0
raidz1 ONLINE 0 0 0
da1 ONLINE 0 0 0
da2 ONLINE 0 0 0
da3 ONLINE 0 0 0
da4 ONLINE 0 0 0
pool: zpool02
state: ONLINE
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
zpool02 ONLINE 0 0 0
raidz1 ONLINE 0 0 0
da9 ONLINE 0 0 0
da10 ONLINE 0 0 0
da11 ONLINE 0 0 0
da12 ONLINE 0 0 0
errors: No known data errors
我几个星期前就能进入游泳池。从那以后,我不得不更换主机的几乎所有硬件,并安装几个主机操作系统。
我的怀疑是,其中一个操作系统安装程序为500GB驱动器中的一个(第一个?)写了一个引导加载程序(或其他内容),并破坏了一些zpool元数据(或其他内容)-“或任何内容”意味着这只是一个非常模糊的想法而这个主题并不完全是我的强项...
关于ZFS,有很多网站,博客,邮件列表等。我在此发布此问题,希望它可以帮助我收集足够的信息,以一种理智,结构化,可控制,知情,知识渊博的方法来取回我的数据,并希望能在相同情况下帮助其他人。
谷歌搜索“ zfs restore”时,第一个搜索结果是《Solaris ZFS管理指南》中的“ ZFS故障排除和数据恢复”一章。在第一个ZFS失败模式部分中,它在“损坏的ZFS数据”段落中说:
数据损坏始终是永久性的,在修复过程中需要特别注意。即使修复或更换了基础设备,原始数据也将永远丢失。
有点令人沮丧。
但是,第二个Google搜索结果是Max Bruning的网络日志,我在那里阅读
最近,有人给我发送了一封电子邮件,该人在一个10TB的ZFS池中存储了15年的视频和音乐,在停电后,它就出现了故障。不幸的是,他没有备份。他在FreeBSD 7上使用ZFS版本6 [...]大约花了一周时间检查了磁盘上的数据之后,我基本上能够还原所有数据。
和
至于ZFS丢失数据,我对此表示怀疑。我怀疑您的数据在那里,但是您需要找到正确的方法来获取它。
(听起来更像是我想听的东西...)
第一步:到底是什么问题?
我如何诊断为什么zpool确切地报告为已损坏?我看到zdb似乎没有在网络上的任何地方被Sun或Oracle正式记录。从其手册页:
NAME
zdb - ZFS debugger
SYNOPSIS
zdb pool
DESCRIPTION
The zdb command is used by support engineers to diagnose failures and
gather statistics. Since the ZFS file system is always consistent on
disk and is self-repairing, zdb should only be run under the direction
by a support engineer.
If no arguments are specified, zdb, performs basic consistency checks
on the pool and associated datasets, and report any problems detected.
Any options supported by this command are internal to Sun and subject
to change at any time.
此外,在2008年6月28日于布拉格举行的Open Solaris Developer Conference上,Ben Rockwood发表了一篇详细的文章,并提供了一个有关Max Bruning 的视频(和mdb)。
在损坏的zpool上以root身份运行zdb会得到以下输出:
[user@host ~]$ sudo zdb zpool01
version=6
name='zpool01'
state=0
txg=83216
pool_guid=16471197341102820829
hostid=3885370542
hostname='host.domain'
vdev_tree
type='root'
id=0
guid=16471197341102820829
children[0]
type='raidz'
id=0
guid=48739167677596410
nparity=1
metaslab_array=14
metaslab_shift=34
ashift=9
asize=2000412475392
children[0]
type='disk'
id=0
guid=4795262086800816238
path='/dev/da5'
whole_disk=0
DTL=202
children[1]
type='disk'
id=1
guid=16218262712375173260
path='/dev/da6'
whole_disk=0
DTL=201
children[2]
type='disk'
id=2
guid=15597847700365748450
path='/dev/da7'
whole_disk=0
DTL=200
children[3]
type='disk'
id=3
guid=9839399967725049819
path='/dev/da8'
whole_disk=0
DTL=199
children[1]
type='raidz'
id=1
guid=8910308849729789724
nparity=1
metaslab_array=119
metaslab_shift=34
ashift=9
asize=2000412475392
children[0]
type='disk'
id=0
guid=5438331695267373463
path='/dev/da1'
whole_disk=0
DTL=198
children[1]
type='disk'
id=1
guid=2722163893739409369
path='/dev/da2'
whole_disk=0
DTL=197
children[2]
type='disk'
id=2
guid=11729319950433483953
path='/dev/da3'
whole_disk=0
DTL=196
children[3]
type='disk'
id=3
guid=7885201945644860203
path='/dev/da4'
whole_disk=0
DTL=195
zdb: can't open zpool01: Invalid argument
我想最后会出现“无效参数”错误,因为zpool01实际上并不存在:在工作中的zpool02上不会发生此错误,但是似乎也没有任何进一步的输出...
好的,在此阶段,最好在文章过长之前发布此内容。
也许有人可以给我一些有关如何从此处继续前进的建议,而在我等待回应时,我将观看视频,仔细阅读上面zdb输出的详细信息,阅读Bens文章并尝试找出问题所在。什么...
20110806-1600 + 1000
更新01:
我想我已经找到了根本原因:Max Bruning很友好,可以非常迅速地回复我的电子邮件,要求输出zdb -lll
。在“良好” raidz1池的一半中的4个硬盘驱动器中,任何一个输出都类似于我在上面发布的内容。但是,在“损坏的”一半的4个驱动器中的前3个中,zdb
报告failed to unpack label
标签2和3。池中的第四个驱动器似乎可以,zdb
显示所有标签。
谷歌搜索错误消息提出了这篇文章。从对该帖子的第一个回复:
使用ZFS,每个物理vdev上有4个相同的标签,在本例中为单个硬盘。L0 / L1位于vdev的开头,L2 / L3位于vdev的结尾。
池中的所有8个驱动器均具有相同型号Seagate Barracuda 500GB。但是,我确实记得我用4个驱动器启动了该池,然后其中一个驱动器死了,并在保修期内由Seagate更换。后来,我又添加了4个驱动器。因此,驱动器和固件标识符不同:
[user@host ~]$ dmesg | egrep '^da.*?: <'
da0: <VMware, VMware Virtual S 1.0> Fixed Direct Access SCSI-2 device
da1: <ATA ST3500418AS CC37> Fixed Direct Access SCSI-5 device
da2: <ATA ST3500418AS CC37> Fixed Direct Access SCSI-5 device
da3: <ATA ST3500418AS CC37> Fixed Direct Access SCSI-5 device
da4: <ATA ST3500418AS CC37> Fixed Direct Access SCSI-5 device
da5: <ATA ST3500320AS SD15> Fixed Direct Access SCSI-5 device
da6: <ATA ST3500320AS SD15> Fixed Direct Access SCSI-5 device
da7: <ATA ST3500320AS SD15> Fixed Direct Access SCSI-5 device
da8: <ATA ST3500418AS CC35> Fixed Direct Access SCSI-5 device
da9: <ATA SAMSUNG HM160JC AP10> Fixed Direct Access SCSI-5 device
da10: <ATA SAMSUNG HM160JC AP10> Fixed Direct Access SCSI-5 device
da11: <ATA SAMSUNG HM160JC AP10> Fixed Direct Access SCSI-5 device
da12: <ATA SAMSUNG HM160JC AP10> Fixed Direct Access SCSI-5 device
我确实记得所有驱动器都具有相同的大小。现在查看驱动器,它表明其中三个的大小已更改,它们缩小了2 MB:
[user@host ~]$ dmesg | egrep '^da.*?: .*?MB '
da0: 10240MB (20971520 512 byte sectors: 255H 63S/T 1305C)
da1: 476940MB (976773168 512 byte sectors: 255H 63S/T 60801C)
da2: 476940MB (976773168 512 byte sectors: 255H 63S/T 60801C)
da3: 476940MB (976773168 512 byte sectors: 255H 63S/T 60801C)
da4: 476940MB (976773168 512 byte sectors: 255H 63S/T 60801C)
da5: 476938MB (976771055 512 byte sectors: 255H 63S/T 60801C) <--
da6: 476938MB (976771055 512 byte sectors: 255H 63S/T 60801C) <--
da7: 476938MB (976771055 512 byte sectors: 255H 63S/T 60801C) <--
da8: 476940MB (976773168 512 byte sectors: 255H 63S/T 60801C)
da9: 152627MB (312581808 512 byte sectors: 255H 63S/T 19457C)
da10: 152627MB (312581808 512 byte sectors: 255H 63S/T 19457C)
da11: 152627MB (312581808 512 byte sectors: 255H 63S/T 19457C)
da12: 152627MB (312581808 512 byte sectors: 255H 63S/T 19457C)
因此,从外观上看,并不是“将引导加载程序写入驱动器之一”的操作系统安装(正如我之前假设的那样),实际上是创建2 MB 主机的新主板(华硕P8P67 LE)保护区位于三个驱动器末尾,这弄乱了我的ZFS元数据。
为什么没有在所有驱动器上创建HPA?我相信这是因为HPA的创建仅在较旧的驱动器上完成,而该错误后来由Seagate硬盘BIOS更新修复:当整个事件在几周前开始时,我运行Seagate的SeaTools来检查是否存在驱动器出现任何物理故障(仍在旧硬件上),我收到一条消息,告诉我某些驱动器需要BIOS更新。当我现在尝试重现该消息的确切详细信息以及固件更新下载的链接时,似乎是因为主板创建了HPA,所以两个SeaTools DOS版本都无法检测到相关的硬盘驱动器-快速invalid partition
或类似的操作当它们开始闪烁时,就是这样。具有讽刺意味的是,他们确实找到了一组三星驱动器。
(我跳过了在非网络系统上的FreeDOS shell中搞砸的痛苦,耗时且最终毫无结果的细节。)最后,我在单独的计算机上安装了Windows 7,以便运行SeaTools Windows版本1.2.0.5。关于DOS SeaTools的最后一句话:不要费心尝试独立启动它们-而是花几分钟时间,用令人敬畏的Ultimate Boot CD制作可启动USB记忆棒-除了DOS SeaTools之外,它还为您带来了许多其他好处有用的工具。
启动时,SeaTools for Windows将显示以下对话框:
这些链接指向序列号检查器(由于某种原因受验证码保护,我的身份是“入侵用户”)和有关固件更新的知识库文章。可能还有其他特定于硬盘驱动器型号的链接以及一些下载内容和其他内容,但我暂时不会遵循该路径:
我不会急于一次更新三个具有截断的分区并且属于损坏的存储池的驱动器的固件。那是自找麻烦。对于初学者来说,固件更新很可能无法撤消-这可能无法挽回地破坏了我取回数据的机会。
因此,我接下来要做的第一件事是对驱动器进行映像并处理副本,因此,如果出现任何问题,可以使用原始文档。这可能会带来额外的复杂性,因为ZFS可能会注意到已交换驱动器(通过驱动器序列号或另一个UUID或其他方式),即使它已精确地dd复制到同一硬盘驱动器模型上。而且,zpool甚至没有直播。天哪,这可能会很棘手。
但是,另一个选择是使用原始驱动器并将镜像驱动器作为备份,但是当原始驱动器出现问题时,我可能会遇到上述复杂性。a,不好。
为了清除三个硬盘驱动器,它们将用作损坏池中有故障的BIOS的三个硬盘的映像替代品,我需要为那里的东西创建一些存储空间,因此我将深入研究硬件盒,并从一些旧驱动器组装一个临时zpool-我还可以用它来测试ZFS如何处理交换dd驱动器。
这可能需要一段时间...
20111213-1930 + 1100
更新02:
确实确实需要一段时间。我已经花了几个月的时间在桌上放着几个打开的计算机机箱,上面挂着大量的硬盘驱动器,而且还用耳塞睡了几个晚上,因为我无法在睡觉前关闭机器,因为它正在执行长时间的关键操作。但是,我终于占了上风!:-)在此过程中,我也学到了很多东西,我想在这里为处于类似情况的任何人分享这些知识。
本文已经比ZFS文件服务器无法运行的任何人都有时间阅读,因此,我将在此处进行详细介绍,并在下面的基本发现中提供答案。
我在过时的硬件盒中挖了深深的空间,以组装足够的存储空间,以将物料从单个500GB驱动器上移出,已将有缺陷的驱动器镜像到该驱动器上。我还必须从USB盒中取出一些硬盘驱动器,以便可以直接通过SATA连接它们。当涉及到更多,不相关的问题时,当我将它们重新投入使用并需要替换zpool时,一些旧驱动器开始出现故障,但是我将跳过这一点。
提示:在某个阶段,总共涉及约30个硬盘驱动器。有了那么多的硬件,将它们正确地堆叠起来是极大的帮助。电缆松动或硬盘驱动器从您的桌子上掉下来肯定不会对您有帮助,并可能进一步损害您的数据完整性。
我花了几分钟的时间制作了一些临时的硬纸板硬盘固定装置,这些固定装置确实有助于保持分类:
具有讽刺意味的是,当我第一次连接旧驱动器时,我意识到必须使用旧版本的zpool创建一个旧zpool,以便测试其中的一些旧版本,但是并不是所有丢失的个人数据都在丢失,因此,稍微减少一点,这意味着需要额外地来回移动文件。
最后,我将有问题的驱动器镜像到备份驱动器,将其用于zpool,并使原始驱动器断开连接。备份驱动器具有较新的固件,至少SeaTools不报告任何必需的固件更新。我使用一个简单的dd从一个设备镜像到另一个设备,例如
sudo dd if=/dev/sda of=/dev/sde
我相信ZFS确实注意到了硬件更改(通过某些硬盘UUID或其他原因),但似乎并不在意。
但是,zpool仍处于相同状态,副本不足/数据损坏。
如前面提到的HPA Wikipedia文章所述,在Linux启动时报告了主机保护区的存在,可以使用hdparm进行调查。据我所知,在FreeBSD上没有可用的hdparm工具,但是到了此时,无论如何我已经将FreeBSD 8.2和Debian 6.0安装为双引导系统,所以我进入了Linux:
user@host:~$ for i in {a..l}; do sudo hdparm -N /dev/sd$i; done
...
/dev/sdd:
max sectors = 976773168/976773168, HPA is disabled
/dev/sde:
max sectors = 976771055/976773168, HPA is enabled
/dev/sdf:
max sectors = 976771055/976773168, HPA is enabled
/dev/sdg:
max sectors = 976771055/976773168, HPA is enabled
/dev/sdh:
max sectors = 976773168/976773168, HPA is disabled
...
因此,问题显然是新主板在驱动器的末端创建了几兆字节的HPA,从而“隐藏”了上面两个ZFS标签,即阻止ZFS看到它们。
涉足HPA似乎是一项危险的业务。在hdparm手册页中,参数-N:
Get/set max visible number of sectors, also known as the Host Protected Area setting.
...
To change the current max (VERY DANGEROUS, DATA LOSS IS EXTREMELY LIKELY), a new value
should be provided (in base10) immediately following the -N option.
This value is specified as a count of sectors, rather than the "max sector address"
of the drive. Drives have the concept of a temporary (volatile) setting which is lost on
the next hardware reset, as well as a more permanent (non-volatile) value which survives
resets and power cycles. By default, -N affects only the temporary (volatile) setting.
To change the permanent (non-volatile) value, prepend a leading p character immediately
before the first digit of the value. Drives are supposed to allow only a single permanent
change per session. A hardware reset (or power cycle) is required before another
permanent -N operation can succeed.
...
就我而言,将HPA删除为:
user@host:~$ sudo hdparm -Np976773168 /dev/sde
/dev/sde:
setting max visible sectors to 976773168 (permanent)
max sectors = 976773168/976773168, HPA is disabled
对于具有HPA的其他驱动器,以相同的方式进行。如果驱动器错误或您指定的有关size参数的说法不合理,则hdparm足够聪明,可以得出:
user@host:~$ sudo hdparm -Np976773168 /dev/sdx
/dev/sdx:
setting max visible sectors to 976773168 (permanent)
Use of -Nnnnnn is VERY DANGEROUS.
You have requested reducing the apparent size of the drive.
This is a BAD idea, and can easily destroy all of the drive's contents.
Please supply the --yes-i-know-what-i-am-doing flag if you really want this.
Program aborted.
之后,我重新启动了最初在其上创建zpool的FreeBSD 7.2虚拟机,并且zpool status再次报告了一个工作池。好极了!:-)
我在虚拟系统上导出了池,然后在主机FreeBSD 8.2系统上重新导入了池。
一些更主要的硬件升级,另一个主板交换,一个ZFS池更新到ZFS 4/15,彻底的清理,现在我的zpool由8x1TB加上8x500GB raidz2部分组成:
[user@host ~]$ sudo zpool status
pool: zpool
state: ONLINE
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
zpool ONLINE 0 0 0
raidz2 ONLINE 0 0 0
ad0 ONLINE 0 0 0
ad1 ONLINE 0 0 0
ad2 ONLINE 0 0 0
ad3 ONLINE 0 0 0
ad8 ONLINE 0 0 0
ad10 ONLINE 0 0 0
ad14 ONLINE 0 0 0
ad16 ONLINE 0 0 0
raidz2 ONLINE 0 0 0
da0 ONLINE 0 0 0
da1 ONLINE 0 0 0
da2 ONLINE 0 0 0
da3 ONLINE 0 0 0
da4 ONLINE 0 0 0
da5 ONLINE 0 0 0
da6 ONLINE 0 0 0
da7 ONLINE 0 0 0
errors: No known data errors
[user@host ~]$ df -h
Filesystem Size Used Avail Capacity Mounted on
/dev/label/root 29G 13G 14G 49% /
devfs 1.0K 1.0K 0B 100% /dev
zpool 8.0T 3.6T 4.5T 44% /mnt/zpool
最后,在我看来ZFS池非常非常难以杀死。创建该系统的来自Sun的人有充分的理由将其称为文件系统中的最后一句话。尊重!