Eu tenho vários TBs de dados pessoais muito valiosos em um zpool que não consigo acessar devido à corrupção de dados. O pool foi originalmente configurado em 2009, aproximadamente, em um sistema FreeBSD 7.2 em execução em uma máquina virtual VMWare sobre um sistema Ubuntu 8.04. A VM do FreeBSD ainda está disponível e funcionando perfeitamente, apenas o sistema operacional host agora mudou para o Debian 6. Os discos rígidos são acessíveis à VM convidada por meio de dispositivos SCSI genéricos VMWare, 12 no total.
Existem 2 piscinas:
- zpool01: 2x 4x 500GB
- zpool02: 1x 4x 160GB
O que funciona está vazio, o quebrado contém todos os dados importantes:
[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
Consegui acessar a piscina há algumas semanas. Desde então, tive que substituir praticamente todo o hardware da máquina host e instalar vários sistemas operacionais.
Minha suspeita é que uma dessas instalações do sistema operacional tenha gravado um carregador de inicialização (ou o que seja) em uma (a primeira?) Das unidades de 500 GB e destruído alguns metadados do zpool (ou o que seja) - 'ou seja o que for' - o que significa que essa é apenas uma ideia muito vaga e esse assunto não é exatamente o meu lado forte ...
Existem muitos sites, blogs, listas de discussão etc. sobre o ZFS. Postei essa pergunta aqui na esperança de que ela me ajude a reunir informações suficientes para uma abordagem sã, estruturada, controlada, informada e com conhecimento para recuperar meus dados - e espero ajudar outra pessoa na mesma situação.
O primeiro resultado da pesquisa ao pesquisar 'zfs recover' é o capítulo Solução de problemas e recuperação de dados do ZFS no Guia de administração do ZFS Solaris. Na primeira seção Modos de falha do ZFS , diz o parágrafo 'Dados corrompidos do ZFS':
A corrupção de dados é sempre permanente e requer consideração especial durante o reparo. Mesmo se os dispositivos subjacentes forem reparados ou substituídos, os dados originais serão perdidos para sempre.
Um pouco desanimador.
No entanto, o segundo resultado de pesquisa do Google é o blog de Max Bruning e, lá, eu li
Recentemente, recebi um e-mail de alguém com 15 anos de vídeo e música armazenados em um pool ZFS de 10 TB que, após uma falha de energia, ficou com defeito. Infelizmente, ele não tinha um backup. Ele estava usando o ZFS versão 6 no FreeBSD 7 [...] Depois de passar cerca de 1 semana examinando os dados no disco, pude restaurar basicamente tudo isso.
e
Quanto ao ZFS perder seus dados, duvido. Suspeito que seus dados estejam lá, mas você precisa encontrar o caminho certo para obtê-los.
(isso soa muito mais como algo que eu quero ouvir ...)
Primeiro passo : Qual é exatamente o problema?
Como posso diagnosticar por que exatamente o zpool é relatado como corrompido? Vejo que existe o zdb que não parece oficialmente documentado pela Sun ou pela Oracle em qualquer lugar da web. Na sua página de manual:
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.
Além disso, Ben Rockwood publicou um artigo detalhado e há um vídeo de Max Bruning falando sobre isso (e mdb) na Open Solaris Developer Conference em Praga em 28 de junho de 2008.
A execução do zdb como root no zpool quebrado fornece a seguinte saída:
[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
Suponho que o erro 'argumento inválido' no final ocorra porque o zpool01 realmente não existe: ele não ocorre no zpool02 em funcionamento, mas também não parece haver mais saída ...
OK, nesta fase, provavelmente é melhor postar isso antes que o artigo fique muito longo.
Talvez alguém possa me dar alguns conselhos sobre como avançar a partir daqui e enquanto espero uma resposta, assisto ao vídeo, analiso os detalhes da saída zdb acima, leia o artigo de Bens e tente descobrir o que é o que...
20110806-1600 + 1000
Atualização 01:
Acho que encontrei a causa raiz: Max Bruning teve a gentileza de responder a um e-mail meu muito rapidamente, solicitando a saída de zdb -lll
. Em qualquer um dos quatro discos rígidos na metade 'boa' do raidz1 do pool, a saída é semelhante à que eu postei acima. No entanto, nas 3 primeiras das 4 unidades na metade 'quebrada', os zdb
relatórios failed to unpack label
para as etiquetas 2 e 3. A quarta unidade no pool parece OK, zdb
mostra todas as etiquetas.
Pesquisando essa mensagem de erro, aparece esta postagem . Desde a primeira resposta a esse post:
Com o ZFS, existem quatro etiquetas idênticas em cada vdev físico, neste caso, um único disco rígido. L0 / L1 no início do vdev e L2 / L3 no final do vdev.
Todas as 8 unidades na piscina são do mesmo modelo, Seagate Barracuda 500GB . No entanto, lembro-me de ter iniciado a piscina com 4 unidades, depois uma delas morreu e foi substituída pela garantia pela Seagate. Mais tarde, adicionei mais 4 unidades. Por esse motivo, os identificadores da unidade e do firmware são diferentes:
[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
Eu me lembro, porém, de que todas as unidades tinham o mesmo tamanho. Olhando para as unidades agora, mostra que o tamanho foi alterado para três delas, elas diminuíram em 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)
Portanto, pelo que parece, não foi uma das instalações do SO que 'gravou um gerenciador de inicialização em uma das unidades' (como eu havia assumido antes); na verdade, era a nova placa-mãe (uma ASUS P8P67 LE ) criando um host de 2 MB área protegida no final de três das unidades que danificaram meus metadados do ZFS.
Por que ele não criou um HPA em todas as unidades? Acredito que isso ocorre porque a criação do HPA é feita apenas em unidades mais antigas com um bug que foi corrigido posteriormente por uma atualização do BIOS do disco rígido da Seagate: Quando todo esse incidente começou há algumas semanas, executei o SeaTools da Seagate para verificar se havia qualquer coisa fisicamente errada com as unidades (ainda no hardware antigo) e recebi uma mensagem informando que algumas das minhas unidades precisam de uma atualização do BIOS. Como agora estou tentando reproduzir os detalhes exatos dessa mensagem e o link para o download da atualização de firmware, parece que desde que a placa-mãe criou o HPA, ambas as versões do SeaTools DOS falharam em detectar os discos rígidos em questão - um rápido invalid partition
ou algo semelhante pisca quando eles começam, é isso. Ironicamente, eles encontram um conjunto de unidades Samsung, no entanto.
(Eu pulei os detalhes dolorosos, demorados e, finalmente, infrutíferos de se mexer em um shell do FreeDOS em um sistema sem rede.) No final, instalei o Windows 7 em uma máquina separada para executar o SeaTools Windows versão 1.2.0.5. Apenas uma última observação sobre o DOS SeaTools: não se preocupe em tentar inicializá-los de maneira independente - em vez disso, invista alguns minutos e faça um pendrive inicializável com o incrível CD Ultimate Boot - que, além do DOS SeaTools, também oferece muitos outros ferramentas úteis.
Quando iniciado, o SeaTools for Windows exibe esta caixa de diálogo:
Os links levam ao Verificador de número de série (que por algum motivo é protegido por uma captura de tela era 'Usuários invasivos') e um artigo da base de conhecimento sobre a atualização do firmware. Provavelmente existem outros links específicos para o modelo do disco rígido e alguns downloads e o que não, mas não vou seguir esse caminho no momento:
Não vou me apressar em atualizar o firmware de três unidades por vez que possuem partições truncadas e fazem parte de um pool de armazenamento quebrado. Isso está pedindo problemas. Para iniciantes, a atualização do firmware provavelmente não pode ser desfeita - e isso pode arruinar irrevogavelmente minhas chances de recuperar meus dados.
Portanto, a primeira coisa que farei a seguir é criar uma imagem das unidades e trabalhar com as cópias, para que haja um original para voltar se algo der errado. Isso pode introduzir uma complexidade adicional, pois o ZFS provavelmente notará que as unidades foram trocadas (por meio do número de série da unidade ou de outro UUID ou qualquer outra coisa), mesmo que sejam cópias dd com bit exato no mesmo modelo de disco rígido. Além disso, o zpool nem está ativo. Rapaz, isso pode ficar complicado.
A outra opção, porém, seria trabalhar com os originais e manter as unidades espelhadas como backup, mas provavelmente terei uma complexidade acima quando algo deu errado com os originais. Naa, não é bom.
Para limpar os três discos rígidos que servirão como substitutos de imagem para os três discos com o BIOS de buggy no pool quebrado, preciso criar algum espaço de armazenamento para as coisas que estão lá agora, então vou me aprofundar na caixa de hardware e monte um zpool temporário a partir de algumas unidades antigas - que também posso usar para testar como o ZFS lida com a troca de unidades dd'd.
Isso pode demorar um pouco ...
20111213-1930 + 1100
Atualização 02:
Isso demorou um pouco, de fato. Passei meses com várias caixas de computador abertas em minha mesa com várias pilhas de discos rígidos penduradas e também dormi algumas noites com tampões para os ouvidos, porque não conseguia desligar a máquina antes de ir para a cama, pois ela estava executando alguma operação crítica demorada . No entanto, eu prevaleci finalmente! :-) Eu também aprendi muito no processo e gostaria de compartilhar esse conhecimento aqui para qualquer pessoa em uma situação semelhante.
Este artigo já é muito mais longo do que qualquer pessoa com um servidor de arquivos ZFS fora de ação tem tempo para ler, por isso vou entrar em detalhes aqui e criar uma resposta com as descobertas essenciais mais adiante.
Eu cavei profundamente na caixa de hardware obsoleta para reunir espaço de armazenamento suficiente para mover o material das unidades únicas de 500 GB para as quais as unidades defeituosas foram espelhadas. Eu também tive que retirar alguns discos rígidos de seus estojos USB, para poder conectá-los diretamente via SATA. Havia mais alguns problemas não relacionados envolvidos e algumas das unidades antigas começaram a falhar quando eu as coloquei novamente em ação, exigindo uma substituição do zpool, mas vou pular isso.
Dica: Em algum momento, havia um total de cerca de 30 discos rígidos envolvidos nisso. Com tanto hardware, é uma enorme ajuda empilhá-los adequadamente; cabos soltos ou disco rígido que caem da sua mesa certamente não ajudarão no processo e podem causar mais danos à integridade dos dados.
Passei alguns minutos criando alguns acessórios de disco rígido improvisados de papelão que realmente ajudaram a manter as coisas organizadas:
Ironicamente, quando conectei as unidades antigas pela primeira vez, percebi que havia um zpool antigo que eu deveria ter criado para testar com uma versão mais antiga de algumas, mas nem todos os dados pessoais que desapareceram, portanto, enquanto a perda de dados era um pouco reduzido, isso significava uma troca adicional de arquivos.
Por fim, espelhei as unidades problemáticas nas unidades de backup, usei as para o zpool e deixei as originais desconectadas. As unidades de backup possuem um firmware mais recente, pelo menos o SeaTools não informa nenhuma atualização de firmware necessária. Fiz o espelhamento com um dd simples de um dispositivo para outro, por exemplo
sudo dd if=/dev/sda of=/dev/sde
Acredito que o ZFS percebe a alteração do hardware (por algum UUID do disco rígido ou o que seja), mas não parece se importar.
No entanto, o zpool ainda estava no mesmo estado, réplicas insuficientes / dados corrompidos.
Conforme mencionado no artigo da HPA Wikipedia mencionado anteriormente, a presença de uma área protegida por host é relatada quando o Linux é inicializado e pode ser investigada usando o hdparm . Até onde eu sei, não há nenhuma ferramenta hdparm disponível no FreeBSD, mas a essa altura, eu já tinha o FreeBSD 8.2 e o Debian 6.0 instalados como sistema de inicialização dupla, então eu inicializei no 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
...
Portanto, o problema obviamente era que a nova placa-mãe criou um HPA de alguns megabytes no final da unidade que 'ocultava' os dois rótulos superiores do ZFS, ou seja, impedia o ZFS de vê-los.
Brincar com a HPA parece um negócio perigoso. Na página do manual hdparm, parâmetro -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.
...
No meu caso, o HPA é removido assim:
user@host:~$ sudo hdparm -Np976773168 /dev/sde
/dev/sde:
setting max visible sectors to 976773168 (permanent)
max sectors = 976773168/976773168, HPA is disabled
e da mesma maneira para as outras unidades com um HPA. Se você pegar a unidade errada ou algo sobre o parâmetro de tamanho especificado não for plausível, o hdparm é inteligente o suficiente para descobrir:
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.
Depois disso, reiniciei a máquina virtual do FreeBSD 7.2 na qual o zpool foi criado originalmente e o status do zpool relatou um pool de trabalho novamente. YAY! :-)
Eu exportei o pool no sistema virtual e reimportei-o no sistema host FreeBSD 8.2.
Algumas atualizações importantes de hardware, outra troca de placas-mãe, uma atualização do pool do ZFS para o ZFS 4/15, uma limpeza completa e agora meu zpool consiste em 8x1TB mais 8x500GB de peças 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
Como última palavra, parece-me que os pools do ZFS são muito, muito difíceis de matar. Os caras da Sun que criaram esse sistema têm todo o motivo para chamá-lo de última palavra em sistemas de arquivos. Respeito!