La Lanterne Rouge

Warning: Geek Inside

Panne de disque, corruption de système de fichiers ext3 et résolution...s

- Posted in Sans catégorie by

Tout démarre par une de mes modestes péripéties geekesques avec mon "cheptel" comme je l'appelle : il s'agit cette fois d'un petit souci - assez prévisible je dois l'avouer - sur l'un de mes deux home servers : Sihaya.

Alors que rien ne le laissait supposer au premier abord, le disque dur interne, d'origine, m'a lâchement lâché après deux ans et demi de bons et loyaux services.

Le truc tout bête : la machine devient subitement inacessible à distance et lors du reboot suivant, fsck détecte des erreurs sur le système de fichiers racine. Je tente évidemment de les corriger automatiquement mais au fur et à mesure de la progression je réalise au nombre que ce sont là plus que de simples petites erreurs bénignes dues à des arrêts forcés comme il en arrive régulièrement (coupures de courant mes amours).

Le système semble sacrément endommagé et je doute pouvoir booter après cette "réparation".

Panne de disque, corruption de système de fichiers ext3 et résolution...s

Analyse préliminaire et backup express

Pour être déjà passé par ce genre d'épreuve, je sais que s'acharner sur fsck génère souvent plus de problèmes que ça n'en règle, car les corrections automatiques ont leurs limites, surtout sur ce que je pressens être une panne matérielle.

J'emporte donc la bête chez moi pour une opération chirurgicale de quelques heures, non sans avoir mis en place en 1h une petite VM Debian sur un autre PC afin de pallier l'absence de Sihaya.

Comme c'est une machine virtuelle elle n'a pas le privilège de porter un nom tiré de la saga Dune, à la place ce sera donc le nom du mentat de la maison Ordos dans le jeu Dune II : Ammon.

Les étapes suivantes consistent à plonger le sujet A dans un profond coma (appuyer sur le bouton power et débrancher les câbles), puis à l'ouvrir délicatement (tournevis et pinces nécessaires, put*** de boîtier scellé) et à lui ôter le disque dur : un Samsung SpinPoint M7 répondant au doux matricule HM321HI.

On branche ensuite ce dernier sur un sujet B en pleine santé (ici : Freeseed), puis on réalise une image complète des données avec ddrescue. Ceci afin de sauver ce qui peut l'être encore avant le "clicliclicliclic" de l'agonie finale (pléonasme inside).

Je prépare au préalable un partage NFS sur mon NAS Synology (merci les 4 To d'espace pour ce genre de besoins urgents) que je monte très simplement depuis Freeseed :

# mkdir /mnt/fedaykin_public_nfs
# mount -t nfs fedaykin:/volume1/public_nfs /mnt/fedaykin_public_nfs

Ah oui, Fedaykin c'est le NAS (suivez un peu enfin).
On lance ensuite la commande ddrescue... puis on attend.

# ddrescue -r3 /dev/sdb /mnt/fedaykin_public_nfs/sihaya_hdd_img_2013-05-26.img sihaya_hdd_img_2013-05-26.img.log

Ici cela signifie que je souhaite réaliser l'image /mnt/fedaykin_public_nfs/sihaya_hdd_img_2013-05-26.img du périphérique /dev/sdb, avec un log appelé sihaya_hdd_img_2013-05-26.img.log dans le dossier courant (ce qui permet de reprendre la création de l'image à l'endroit où elle s'était arrêtée avec la même commande si quelque chose tourne mal) et enfin que je souhaite réessayer la lecture des secteurs défectueux 3 fois maximum.

La création de l'image aura pris une petite journée, démarrant sur un petit 7 Mo/s et s'achevant sur un ridicule 4 Mo/s pour 320 Go de données.

L'information importante que l'on tire de ces débits est qu'il y a effectivement quelque chose qui ne tourne pas rond. Le disque est peut-être un 2,5" SATA en 5400 rpm, mais on devrait au moins dépasser les 30 Mo/s en lecture de données brutes. ddrescue comme dd dont il s'inspire, travaille directement avec les périphériques et non au dessus du système de fichiers, ce qui fait que d'une part le contenu n'importe pas (nombreux petits fichiers ou au contraire fichiers volumineux), et d'autre part, l'image finale aura la taille du contenant et non du contenu visible (ici donc 320 Go soit 298,02 GiB).

Et maintenant, réparons

Une fois le contenu sécurisé, j'ai pu me mettre à bidouiller le disque sans ménagement.

J'espérais secrètement que la panne ne concernait que certains secteurs défectueux et que les utilitaires spécialisés présents sur l'indispensable Utimate Boot CD pourraient éviter la greffe (= le rachat en catastrophe d'un disque équivalent). Mais après un long combat acharné je n'ai pu que corriger le système de fichiers sans écarter les secteurs malades ni obtenir de garanties de la part de S.M.A.R.T. Ce qui ne représentait je le savais bien, qu'un sursis temporaire et trompeur.

Du côté de l'image, et à présent que ce support était fiable, j'ai voulu voir s'il était possible de réparer proprement la première partition dans l'image elle-même.

Il s'avère que c'est très possible et cela très simplement au moyen de fsck. On doit d'abord monter la partition désirée sur un périphérique de loopback (/dev/loopX), opération que beaucoup connaissent déjà pour l'avoir effectuée avec des images ISO de CD ou DVD.

Pour cela, il nous faut d'abord connaître la structure exacte des partitions, que l'on récupère avec sfdisk :

# sfdisk -l -uS /mnt/fedaykin_public_nfs/sihaya_hdd_img_2013-05-26.img
Disk sihaya_hdd_img_2013-05-26.img: cannot get geometry

Disk sihaya_hdd_img_2013-05-26.img: 38913 cylinders, 255 heads, 63 sectors/track
Warning: extended partition does not start at a cylinder boundary.
DOS and Linux will interpret the contents differently.
Units = sectors of 512 bytes, counting from 0

    Device                    Boot     Start       End   #sectors  Id  System
sihaya_hdd_img_2013-05-26.img1   *      2048  39999487   39997440  83  Linux
sihaya_hdd_img_2013-05-26.img2      39999488  43999231    3999744  82  Linux swap
sihaya_hdd_img_2013-05-26.img3      44001278 625139711  581138434   5  Extended
sihaya_hdd_img_2013-05-26.img4             0         -          0   0  Empty
sihaya_hdd_img_2013-05-26.img5      44001280 597798911  553797632  83  Linux
sihaya_hdd_img_2013-05-26.img6     597800960 625139711   27338752  83  Linux

Paramètres :

-l : pour lister les partitions
-uS : pour afficher les tailles en secteurs (ici de 512 octets)

Puis on monte la première partition :

# losetup -o 1048576 --sizelimit 20478689280 /dev/loop0 sihaya_hdd_img_2013-05-26.img

Paramètres :

-o 1048576 : l'offset (décalage) de départ, c'est-à-dire le début de la partition en octets, soit : 1048576 = 512 x 2048 (la valeur "Start" retournée par sfdisk)

--sizelimit 20478689280 : la taille de la partition toujours en octets, soit : 20478689280 = 512 x 39997440 (la valeur "#sectors" retournée par sfdisk)

On peux ensuite lancer fsck sur le périphérique de loopback :

# fsck -p /dev/loop0
fsck from util-linux-ng 2.17.2
e2fsck 1.41.12 (17-May-2010)
/dev/loop0 contient un système de fichiers comportant des erreurs, vérification forcée.
Passe 1 : vérification des i-noeuds, des blocs et des tailles
I-noeud 1038729, i_blocs est 77088, devrait être 68896. Corriger ? oui
I-noeud 1105273, i_blocs est 93648, devrait être 85456. Corriger ? oui
I-noeud 1120206, i_blocs est 128, devrait être 104. Corriger ? oui
I-noeud 1120207, i_blocs est 120, devrait être 104. Corriger ? oui

[ ... ]

Passe 2 : vérification de la structure des répertoires
« . » manquant dans l'i-noeud de répertoire 1170843.
Corriger ? oui
Numéro d'i-noeud invalide pour « . » dans l'i-noeud de répertoire 1170843.
Corriger ? oui
l'entrée de répertoire pour « . » dans ... (1170843) est grande.
Scinder ? oui

[ ... ]

Passe 5 : vérification de l'information du sommaire de groupe
différences de bitmap de blocs:  -(4501156--4501503) -(4501672--4501894) -(4501996--4502479) -(4502481--4503016) -(4503018--4503066) -(4503093--4503297) -(4503304--4503489) -(4503496--4503551) -(4503587--4503589) -(4503603--4503604) -(4503680--4503684) -(4503700--4503705) -(4503770--4503772) -(4503849--4503854) -4508400 -(4508409--4508422) -(4508425--4508433) -(4509561--4509562) -(4509576--4509622) -(4509624--4509667) -(4509692--4509695) -(4509800--4510208) -(4511615--4511616) -(4512644--4513096) -(4694602--4694620) -(4694641--4694675) -(4694719--4694742) -(4694761--4694800) -(4694849--4694851) -(4694877--4694888) -(4694902--4694918) -(4694932--4694961) -(4694975--4694976) -(4694990--4694991) -(4695005--4695011) -(4695025--4695041) -(4695055--4695086) -(4695100--4695149) -(4696155--4696157) -(4702347--4702349) -4702375 -(4702380--4702382) -(4702437--4702536) -(4702544--4702560) -(4703182--4703317) -(4703320--4703322) -(4703417--4703426) -(4703936--4703943) -(4704155--4704170) -4708490 -4713358 -(4713360--4713381) -4713824 -4714067 -4717073 -(4720246--4720258) -(4720264--4720274) -4791417
Corriger ? oui

Ah oui y'a des erreurs. Beaucoup même. Mais on espère que fsck aura pu remettre suffisamment d'ordre dans les fichiers pour m'éviter de devoir réinstaller la machine de zéro.

On démonte ensuite la partition :

# losetup -d /dev/loop0

et l'image du disque est à présent prête à être copiée sur un disque neuf, alors en attente de réception après commande express chez un discounter.

Restauration et croisage de doigts

J'ai commandé un Western Digital Scorpio Blue de 320 Go en guise de remplaçant (toujours en 5400 rpm). À 43,00 € livraison comprise ce n'est vraiment pas un investissement lourd. J'espère même obtenir de meilleures performances qu'avec le disque d'origine de la machine.

Une fois reçu, il me suffit de le brancher sur la même machine qui m'avait permis de réaliser l'image, de remonter le même partage NFS depuis le NAS, et d'effectuer simplement un :

# dd if=/mnt/fedaykin_public_nfs/sihaya_hdd_img_2013-05-26.img of=/dev/sdb

afin de recréer d'un coup la structure des partitions telle qu'elle était sur le disque d'origine, et bien sûr rétablir le contenu de ces partitions.

Puis je fixe le disque sur la carte mère à l'emplacement prévu, et j'insère celle-ci dans le boîtier (j'ose espérer que ces étapes sont réalisées par une machine en usine tellement c'est ch**** à faire rentrer sans rien casser). Je rebranche les câbles, un clavier et une souris, et je presse le bouton d'allumage...

Le boot se passe étrangement bien, et le bureau apparaît rapidement à l'écran (c'est un serveur 99% du temps mais il me sert également de desktop, je rappelle). J'en profite pour mettre le système à jour afin d'être sûr de tourner sur un kernel tout propre.

De prime abord, un seul bémol est à noter : MySQL refuse de démarrer, la faute à une corruption des fichiers de base de données (situés sur la partition qui a souffert). Qu'à cela ne tienne, un job réalise des dumps hebdomadaires, je n'ai qu'à supprimer le contenu du dossier /var/lib/mysql, relancer le daemon et restaurer les dumps le plus récent de toutes les bases.

J'ai réalisé en passant que si je sauvegardais bien le contenu des bases applicatives, je ne sauvegardais par contre pas celle de MySQL même. Il m'a donc fallu recréer à la main les utilisateurs et permissions associées (heureusement ce n'était pas difficile de les retrouver).

Une fois ces petites tracasseries réglées, j'ai simplement laissé la machine tourner comme d'habitude quelques jours.

Aïe : Bad entry in directory

Puis au cours d'une petite opération banale d'administration via Webmin, je remarque que celui-ci n'est pas à jour. Depuis la version 1.6 si je me souviens bien, un bouton permet de lancer la mise à jour très simplement depuis la page d'accueil, ce que je fais en toute confiance.

L'installation se déroule mais je remarque immédiatement que le nombre de lignes qui s'affiche ne correspond pas vraiment à une issue positive. En les analysant je constate que toutes les copies de fichiers ont échoué pour cause de "Read-only file system"... Aïe aïe aïe... pas bon du tout ça.

En consultant dmesg je constate que la partition racine a effectivement été remontée en lecture seule par le noyau, suite à l'erreur "ext3_dx_find_entry: bad entry in directory".

[  120.902475] EXT3-fs error (device sda1): ext3_dx_find_entry: bad entry in directory #1162269: rec_len is smaller than minimal - offset=12288, inode=0, rec_len=0, name_len=0
[  120.902496] Aborting journal on device sda1.
[  120.902994] Remounting filesystem read-only

Je tente de forcer le remontage en lecture-écriture mais il échoue. En dernier recours, je tente le reboot en forçant la vérification du système de fichiers.

# shutdown -rF now

fsck semble faire son oeuvre au redémarrage et corrige quelques erreurs. Bon. Je retente la mise à jour de Webmin.

Rebelote : installation qui échoue, et système de fichiers racine en lecture seule, avec pour seule issue possible le reboot. Je tente à nouveau avec fsck, et celui-ci semble corriger les mêmes erreurs que précédemment... Étrange.

Joyeux Novell

Je décide de confier une donnée personnelle de plus à mon ami Google en recherchant le message d'erreur observé dans les logs du noyau un peu plus tôt.

Puis après plusieurs résultats infructueux sur les forums d'Ubuntu (qui auraient presque tendance à polluer les résultats, mais c'est un autre débat) je tombe enfin sur un message clair et efficace chez Novell : http://www.novell.com/support/kb/doc.php?id=3554036

Dans l'erreur très similaire qui est présentée, il s'agirait en fait d'un fichier qui aurait été marqué de manière invalide comme étant un dossier. Rien d'étrange à cela après la défaillance du disque dur et les réparations automatiques de fsck (je ne lui en veux pas pour autant).

La solution est simplement de trouver le fichier concerné et... de le supprimer. Rien de plus simple à première vue car la démarche est présentée : utiliser find et son option -inum qui permet de rechercher un fichier par son i-noeud (inode). Son i-noeud je le connais, il est noté dans la ligne d'erreur du log du noyau : 1162269.

Problème : le simple fait d'accéder à ce fichier, par find ou rm déclenche immédiatement l'erreur et entraîne le remontage de la partition en lecture seule. Impossible donc de réaliser l'opération, sauf depuis un Live CD. Je redégaine donc mon UBCD et lance la session de Parted Magic (mais tout Live CD convient a priori).

Montage de la partition et recherche du fichier :

# mount /dev/sdb1 /mnt
# find /mnt -inum 1162269
/usr/share/webmin/sshd/help

/usr/share/webmin/sshd/help, c'est donc lui ! Voilà pourquoi l'erreur apparaissait lors de la mise à jour de Webmin !

Mais cela ne correspond pas exactement à l'erreur décrite par l'article de Novell car il s'agit d'un dossier et non d'un fichier. Peu importe, la suppression devrait résoudre le problème anyway.

# rm -rf /usr/share/webmin/sshd/help

Une dernière recherche de l'i-noeud pour vérifier :

# find /mnt -inum 1162269

qui ne me retourne rien. Tout va bien, on peut rebooter.

Je retente une énième fois la mise à jour de Webmin... et ça passe ! Enfin !

Se pourrait-il que d'autres erreurs similaires se cachent encore dans les tréfonds de mon système de fichiers ? Pour répondre à cela, une petite commande qui va parcourir l'ensemble de l'arborescence du système de fichiers devrait suffire :

# find / >/dev/null 2>&1

qui s'achève en quelques minutes et ne déclenche rien dans dmesg. Donc a priori - je touche du boa et du Python - le système de fichiers est propre.

Ah... les joies d'un disque dur qui tombe... toujours aussi fun à gérer... (irony inside)

Cela m'aura quand même permis d'en apprendre un peu plus sur les pannes de disque et leur impact sur les partitions et les données qu'elles contiennent, ainsi que de faire une piqûre de rappel concernant les "gestes de premiers secours" à effectuer.

La règle de base ici restant : ne pas perdre une minute. Un disque qui commence à flancher doit être pris en charge rapidement, et une sauvegarde intégrale de son contenu effectuée, par exemple avec un utilitaire adapté comme ddrescue, disponible sur toutes les distributions.

Mais l'utilitaire n'est rien sans l'espace où placer l'image créée. C'est pourquoi il est crucial d'avoir un système de stockage volumineux à disposition (comme un NAS ou un disque dur externe), avec de quoi contenir une image complète d'un disque moyen (ce qui représente aujourd'hui environ 1 à 1,5 To).

Si toutes ces conditions sont réunies, il est souvent possible de récupérer la majorité des données avant la panne complète.

Bien sûr, cela ne remplace pas les indispensables sauvegardes régulières sur un support séparé ! Mais je ne vous apprends rien :-)