48 votes

ZFS sous FreeBSD : récupération des données corrompues

J'ai plusieurs To de données personnelles très précieuses dans un zpool auquel je ne peux pas accéder en raison d'une corruption des données. Le pool a été initialement mis en place en 2009 environ sur un système FreeBSD 7.2 fonctionnant à l'intérieur d'une machine virtuelle VMWare au-dessus d'un système Ubuntu 8.04. La VM FreeBSD est toujours disponible et fonctionne correctement, seul le système d'exploitation hôte a changé pour Debian 6. Les disques durs sont accessibles à la VM invitée au moyen de périphériques SCSI génériques VMWare, 12 au total.

Il y a deux piscines :

  • zpool01 : 2x 4x 500GB
  • zpool02 : 1x 4x 160GB

Celui qui fonctionne est vide, celui qui est cassé contient toutes les données 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

J'ai pu accéder à la piscine il y a quelques semaines. Depuis, j'ai dû remplacer la quasi-totalité du matériel de la machine hôte et installer plusieurs systèmes d'exploitation hôtes.

Je pense que l'une de ces installations de système d'exploitation a écrit un bootloader (ou autre) sur l'un (le premier ?) des disques de 500 Go et a détruit des métadonnées zpool (ou autre) - 'ou autre' signifiant qu'il s'agit d'une idée très vague et que ce sujet n'est pas vraiment mon point fort...


Il existe de nombreux sites web, blogs, listes de diffusion, etc. sur ZFS. Je pose cette question ici dans l'espoir qu'elle m'aidera à rassembler suffisamment d'informations pour adopter une approche saine, structurée, contrôlée, informée et bien informée afin de récupérer mes données - et qu'elle aidera quelqu'un d'autre dans la même situation.


Le premier résultat de la recherche "zfs recover" sur Google est le suivant Dépannage et récupération des données ZFS chapitre du Guide d'administration de Solaris ZFS. Dans le premier Modes de défaillance de ZFS il est indiqué dans le paragraphe "Corrupted ZFS Data" (données ZFS corrompues) :

L'altération des données est toujours permanente et nécessite une attention particulière lors de la réparation. Même si les dispositifs sous-jacents sont réparés ou remplacés, les données d'origine sont perdues à jamais.

Un peu décourageant.

Cependant, le deuxième résultat de la recherche sur Google est Le blog de Max Bruning et j'y ai lu

Récemment, j'ai reçu un courriel d'une personne qui avait stocké 15 ans de vidéo et de musique dans un pool ZFS de 10 To qui, après une panne de courant, était devenu défectueux. Il n'avait malheureusement pas de sauvegarde. Il utilisait la version 6 de ZFS sur FreeBSD 7 [...] Après avoir passé environ une semaine à examiner les données sur le disque, j'ai pu restaurer la quasi-totalité des données.

y

Quant à la perte de données par ZFS, j'en doute. Je pense que vos données sont là, mais que vous devez trouver le bon moyen d'y accéder.

(cela ressemble tellement plus à quelque chose que j'aimerais entendre...)

Première étape : Quel est exactement le problème ?

Comment puis-je diagnostiquer la raison exacte pour laquelle le zpool est signalé comme étant corrompu ? Je vois qu'il y a zdb qui ne semble pas être officiellement documenté par Sun ou Oracle sur le web. D'après sa page de manuel :

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.

Par ailleurs, Ben Rockwood a publié un article détaillé et il y a un vidéo de Max Bruning en parlant (et de mdb) à la conférence des développeurs Open Solaris à Prague le 28 juin 2008.

L'exécution de zdb en tant que root sur le zpool cassé donne la sortie suivante :

[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

Je suppose que l'erreur "argument invalide" à la fin est due au fait que le zpool01 n'existe pas : Elle ne se produit pas sur le zpool02 qui fonctionne, mais il ne semble pas y avoir d'autre sortie non plus...

OK, à ce stade, il est probablement préférable de poster ceci avant que l'article ne devienne trop long.

Peut-être que quelqu'un peut me donner des conseils sur la façon d'aller de l'avant à partir de maintenant et pendant que j'attends une réponse, je vais regarder la vidéo, examiner les détails de la sortie zdb ci-dessus, lire l'article de Bens et essayer de comprendre ce qu'il en est...


20110806-1600+1000

Mise à jour 01 :

Je pense avoir trouvé la cause première : Max Bruning a eu la gentillesse de répondre très rapidement à un de mes courriels, en demandant la sortie de zdb -lll . Sur n'importe lequel des 4 disques durs de la "bonne" moitié raidz1 du pool, la sortie est similaire à ce que j'ai posté ci-dessus. Cependant, sur les 3 premiers des 4 disques de la moitié "cassée", la sortie est similaire à ce que j'ai posté ci-dessus, zdb rapports failed to unpack label pour les étiquettes 2 et 3. Le quatrième lecteur du pool semble correct, zdb affiche toutes les étiquettes.

En cherchant ce message d'erreur sur Google, on obtient ce poste . Extrait de la première réponse à ce message :

Avec ZFS, il s'agit de 4 éléments identiques physique, dans ce cas un seul disque dur. L0/L1 au début du vdev, et L2/L3 à la fin du vdev.

Les 8 disques du pool sont tous du même modèle, Seagate Barracuda 500GB . Cependant, je me souviens que j'ai commencé le pool avec 4 disques, puis l'un d'entre eux est mort et a été remplacé sous garantie par Seagate. Plus tard, j'ai ajouté 4 autres disques. C'est pourquoi les identifiants des lecteurs et des microprogrammes sont différents :

[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 

Je me souviens cependant que tous les lecteurs avaient la même taille. En regardant les disques maintenant, on voit que la taille a changé pour trois d'entre eux, ils ont rétréci de 2 Mo :

[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)

Il semble donc que ce ne soit pas l'une des installations du système d'exploitation qui ait "écrit un bootloader sur l'un des disques" (comme je l'avais supposé auparavant), mais bien la nouvelle carte mère (un ASUS P8P67 LE ) en créant un fichier de 2 MB zone protégée d'accueil à la fin de trois des disques, ce qui a perturbé mes métadonnées ZFS.

Pourquoi n'a-t-il pas créé un HPA sur tous les lecteurs ? Je pense que c'est parce que la création d'un HPA ne se fait que sur les anciens disques avec un bug qui a été corrigé plus tard par une mise à jour du BIOS du disque dur Seagate. SeaTools pour vérifier s'il y a un problème physique avec les disques (toujours sur l'ancien matériel) et j'ai reçu un message me disant que certains de mes disques ont besoin d'une mise à jour du BIOS. Comme j'essaie maintenant de reproduire les détails exacts de ce message et le lien vers le téléchargement de la mise à jour du firmware, il semble que depuis que la carte mère a créé le HPA, les deux versions DOS de SeaTools n'ont pas détecté les disques durs en question. invalid partition ou quelque chose de similaire clignote lorsqu'ils démarrent, c'est tout. Ironiquement, ils ont trouvé un jeu de disques Samsung.

(J'ai passé sous silence les détails douloureux, chronophages et finalement infructueux de l'utilisation d'un Shell FreeDOS sur un système non connecté à un réseau). Finalement, j'ai installé Windows 7 sur une machine séparée afin d'exécuter la version 1.2.0.5 de SeaTools Windows. Une dernière remarque sur les SeaTools DOS : Ne vous embêtez pas à essayer de les démarrer de manière autonome - à la place, investissez quelques minutes et créez une clé USB amorçable avec l'impressionnant logiciel SeaTools. CD d'amorçage ultime - qui, outre DOS SeaTools, vous permet d'obtenir de nombreux autres outils très utiles.

Lorsqu'ils sont lancés, les SeaTools pour Windows affichent cette boîte de dialogue :

SeaTools Firmware Update Dialog

Les liens mènent à la Vérificateur de numéro de série (qui, pour une raison quelconque, est protégé par un captcha - le mien était "Utilisateurs invasifs") et un article de la base de connaissances sur la mise à jour du micrologiciel. Il y a probablement d'autres liens spécifiques au modèle de disque dur et quelques téléchargements et autres, mais je ne suivrai pas cette voie pour le moment :

Je ne me précipiterai pas pour mettre à jour le micrologiciel de trois disques à la fois dont les partitions sont tronquées et qui font partie d'un pool de stockage défectueux. C'est s'exposer à des problèmes. Tout d'abord, la mise à jour du micrologiciel ne pourra probablement pas être annulée, ce qui pourrait irrémédiablement ruiner mes chances de récupérer mes données.

Par conséquent, la toute première chose que je vais faire est de créer une image des disques et de travailler avec les copies, afin de pouvoir revenir à l'original en cas de problème. Cela pourrait introduire une complexité supplémentaire, car ZFS remarquera probablement que les disques ont été échangés (au moyen du numéro de série du disque ou d'un autre UUID ou autre), même s'il s'agit de copies dd exactes au bit près sur le même modèle de disque dur. De plus, le zpool n'est même pas actif. Bon sang, ça risque d'être compliqué.

L'autre option serait de travailler avec les disques d'origine et de conserver les disques en miroir comme sauvegarde, mais je me heurterais alors probablement à la complexité susmentionnée en cas de problème avec les disques d'origine. Naa, pas bon.

Afin d'éliminer les trois disques durs qui serviront de remplacements imagés pour les trois disques avec le BIOS bogué dans le pool cassé, je dois créer de l'espace de stockage pour le matériel qui s'y trouve actuellement, je vais donc fouiller dans la boîte de matériel et assembler un zpool temporaire à partir de quelques vieux disques - que je peux également utiliser pour tester la façon dont ZFS gère l'échange de disques dd's.

Cela pourrait prendre un certain temps...


20111213-1930+1100

Mise à jour 02 :

Cela a pris un certain temps. J'ai passé des mois avec plusieurs boîtiers d'ordinateur ouverts sur mon bureau, avec diverses piles de disques durs qui traînaient, et j'ai également dormi quelques nuits avec des bouchons d'oreille, parce que je ne pouvais pas éteindre la machine avant d'aller me coucher, car elle exécutait une opération critique de longue durée. Cependant, j'ai finalement gagné ! :-) J'ai également beaucoup appris au cours de ce processus et j'aimerais partager ces connaissances ici pour quiconque se trouve dans une situation similaire.

Cet article est déjà beaucoup plus long que ce que toute personne ayant un serveur de fichiers ZFS hors service a le temps de lire, c'est pourquoi je vais entrer dans les détails ici et créer une réponse avec les résultats essentiels plus bas.

J'ai creusé dans la boîte de matériel obsolète pour rassembler suffisamment d'espace de stockage pour déplacer les données des disques de 500 Go sur lesquels les disques défectueux étaient mis en miroir. J'ai également dû sortir quelques disques durs de leurs boîtiers USB, afin de pouvoir les connecter directement via SATA. Il y a eu d'autres problèmes, sans rapport, et certains des anciens disques ont commencé à tomber en panne lorsque je les ai remis en service, ce qui a nécessité un remplacement zpool, mais je vais passer sur ce point.

Conseil : À un moment donné, une trentaine de disques durs au total ont été impliqués dans cette affaire. Avec une telle quantité de matériel, il est extrêmement utile de l'empiler correctement ; les câbles qui se détachent ou les disques durs qui tombent de votre bureau ne facilitent certainement pas le processus et risquent d'endommager davantage l'intégrité de vos données.

J'ai passé quelques minutes à créer des supports de disques durs en carton de fortune, ce qui m'a vraiment aidé à garder les choses en ordre :

some of the make-shift storage spacejust a bunch of screws plus some cardboardthe fan is not exactly required, the stack is from an earlier projectthe distance pieces aren't required either...

Ironiquement, lorsque j'ai connecté les anciens disques la première fois, je me suis rendu compte qu'il y avait un ancien zpool que j'avais dû créer pour tester une ancienne version de certaines données personnelles, mais pas toutes, qui ont disparu, de sorte que si la perte de données a été quelque peu réduite, cela a entraîné des déplacements supplémentaires de fichiers.

Enfin, j'ai mis en miroir les disques problématiques sur des disques de sauvegarde, je les ai utilisés pour le zpool et j'ai laissé les disques d'origine déconnectés. Les disques de sauvegarde ont un firmware plus récent, du moins SeaTools ne signale aucune mise à jour de firmware nécessaire. J'ai effectué la mise en miroir avec un simple dd d'un périphérique à l'autre, par exemple

sudo dd if=/dev/sda of=/dev/sde

Je crois que ZFS remarque le changement de matériel (par un UUID de disque dur ou autre), mais ne semble pas s'en préoccuper.

Cependant, le zpool était toujours dans le même état, insuffisance de répliques / données corrompues.

Comme indiqué dans le Article de Wikipédia sur l'APH mentionnée précédemment, la présence d'une zone protégée par l'hôte est signalée au démarrage de Linux et peut être examinée à l'aide de la fonction hdparm . Pour autant que je sache, il n'y a pas d'outil hdparm disponible sous FreeBSD, mais à ce moment-là, j'avais de toute façon FreeBSD 8.2 et Debian 6.0 installés en tant que système dual-boot, et j'ai donc démarré sous 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
   ...

Le problème était donc que la nouvelle carte mère créait un HPA de quelques mégaoctets à l'extrémité du disque qui "cachait" les deux étiquettes ZFS supérieures, c'est-à-dire qu'il empêchait ZFS de les voir.


Il semble dangereux de jouer avec la HPA. Extrait de la page de manuel hdparm, paramètre -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.
  ...

Dans mon cas, le HPA est retiré de cette manière :

user@host:~$ sudo hdparm -Np976773168 /dev/sde

/dev/sde:
 setting max visible sectors to 976773168 (permanent)
 max sectors   = 976773168/976773168, HPA is disabled

et de la même manière pour les autres lecteurs avec un HPA. Si vous vous trompez de disque ou si le paramètre de taille que vous spécifiez n'est pas plausible, hdparm est suffisamment intelligent pour s'en rendre compte :

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.

Après cela, j'ai redémarré la machine virtuelle FreeBSD 7.2 sur laquelle le zpool avait été créé à l'origine et zpool status a signalé un pool fonctionnel à nouveau. YAY ! :-)

J'ai exporté le pool sur le système virtuel et je l'ai réimporté sur le système hôte FreeBSD 8.2.

D'autres mises à niveau matérielles majeures, un autre changement de carte mère, une mise à jour du pool ZFS vers ZFS 4 / 15, un nettoyage complet et maintenant mon pool ZFS se compose de 8x1TB plus 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

Enfin, il me semble que les pools ZFS sont très, très difficiles à détruire. Les gars de Sun qui ont créé ce système ont toutes les raisons de l'appeler le dernier mot en matière de systèmes de fichiers. Respect !

-2voto

npn Points 1

Si c'était juste un problème de partition, je ferais les partitions du disque + MBR et je mettrais la partition à la bonne taille...

Si vous ne formatez pas une partition, la création ou la modification de la table de partition n'affecte rien (vous pouvez donc revenir en arrière !) tant qu'il n'y a pas de format, la plupart des données sont toujours présentes/accessibles. Si la nouvelle partition est insérée à la fin du disque, vous pouvez avoir des fichiers corrompus là où les nouvelles données ont été écrites, c'est pourquoi vous n'êtes bon que pour cette astuce jusqu'à ce que vous formatiez (nouvelle table de partition, table de fichiers, etc...).

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X