Hitachi meurt dur, bash et techno-nécrophilie

Attention: la solution décrite dans cet article n'est pas professionnelle, elle a peut-être été créée sur la base d'une mauvaise compréhension de la structure et des principes de fonctionnement des disques durs. La répétition des étapes ci-dessus peut endommager l'équipement.


Récemment, je suis tombé sur un article sur l'utilisation de vieux disques durs avec de mauvais blocs et j'ai pensé que mon expérience pourrait également être intéressante pour quelqu'un.


Une fois, des connaissances m'ont demandé d'aider à gérer un ordinateur portable sur lequel elles ne pouvaient pas réinstaller Windows. L'ordinateur portable, à en juger par l'apparence, a eu une vie difficile: fissures dans le boîtier, coins bosselés, supports cassés. Il est clair que le problème est l'endommagement du disque dur à la suite de nombreux coups, ce qui a également été confirmé par smart: plus de 200 opérations de capteur G, 500 décomptes de secteur réaffectés et il y a toujours en attente de courant. Eh bien, les gens, bien sûr, j'ai installé le SSD et copié les informations de leur vis dans l'image avec la commande:


dd if=/dev/sdb of=/media/hddimages/ht320.img bs=409600 conv=noerror,notrunc,sync 

Les paramètres "conv = noerror, notrunc, sync" sont nécessaires pour qu'en cas d'erreur de lecture de certains secteurs, des zéros soient écrits à ces adresses dans le fichier de sortie, et les données soient écrites à leur place sans biais.


Il arrive que lors de la lecture en gros blocs (400 Ko), le disque ne lit pas le bloc entier, et les plus petits ne lisent pas seulement 1 secteur. Les secteurs ici sont de 4 ko, donc après le premier passage de dd, s'il y avait des erreurs de lecture, j'essaye de relire ces sections en blocs de 4 ko:


 n=<>;dd if=/dev/sdb of=/media/hddimages/ht320.img bs=4096 conv=noerror,notrunc,sync skip=$n seek=$n count=100 

Les paramètres de saut et de recherche sont nécessaires pour que la lecture et l'écriture commencent par le même retrait à partir du début du disque. L'indentation elle-même est tirée de la sortie de la première exécution dd, uniquement pour correspondre à la taille du bloc, multipliez le nombre par 100.


Parfois, lors de l'accès à des secteurs défectueux, les disques gèlent pendant longtemps, à tel point que seule la reconnexion à l'alimentation aide et il y a environ 5 ans, un complexe matériel-logiciel (avec même un microcontrôleur) a été créé pour automatiser la lecture des mauvais disques avec une reconnexion automatique de l'alimentation en cas de trop un long manque de réponse. C'était intéressant et permis, en connectant le disque dur et en entrant la commande, après 10 jours d'obtenir l'image la plus complète. Mais le héros expérimental de l'article n'a pas tenu bon, il n'était donc pas nécessaire d'obtenir la béquille lourde décrite.


Donc, le disque a été considéré, j'ai monté toutes les sections de l'image via losetup avec les décalages du début des partitions de fdisk, multipliés par la taille du bloc logique en MBR - 512 octets, je copie toutes les données aux personnes sur un nouveau SSD. Si le disque n'était pas monté ou que de nombreux fichiers ne pouvaient pas être lus, j'ouvrirais l'image avec R-Studio et la restaurerais à travers elle, mais à partir de l'image elle-même.


Mais le disque, bien qu'il soit battu, est dommage à jeter, alors j'ai décidé de le réanimer. Théoriquement, le contrôleur de disque marque les secteurs comme endommagés et réaffecte les secteurs de sauvegarde à leurs adresses en cas de tentatives répétées infructueuses d'écriture ou d'erreurs de lecture irrécupérables (à l'aide d'ECC).


J'essaie d'abord d'essuyer le disque (dd if = / dev / zero ...) et de lire ensuite: la vitesse est également instable, le disque se fige et parfois des erreurs d'entrée / sortie se produisent, mais dans la puce, le nombre de relocks et de suspensions augmente. Après plusieurs cycles, la puce n'a pas beaucoup changé, les suspensions ne se sont pas déplacées et des blocages avec des erreurs se produisent à chaque fois aux mêmes endroits ou très proches. J'essaie de remapper manuellement de force avec la commande "hdparm --make-bad-sector", mais cela ne fonctionne pas sur ce modèle et je me rends compte que l'effacement-lecture, ainsi que l'écriture-lecture, ne sera pas en mesure d'afficher tous les problèmes. En effet, si un bit endommagé, quel que soit ce qu'il a essayé d'y écrire, est plus susceptible de se lire comme "1", alors lors de l'écriture, "1", la lecture suivante se fera sans erreur, mais lors de l'écriture d'un modèle différent, il peut il y a suffisamment d'incohérences pour que l'ECC échoue et qu'une erreur de lecture irréparable se produise, et après plusieurs de ces cas, le secteur a reçu le statut "Mauvais". Soit dit en passant, la valeur enregistrée peut être si superposée à la distribution des bits endommagés qu'une valeur incorrecte de lecture satisfera même l'ECC. Par conséquent, pour maximiser l'identification de tous les secteurs défectueux, vous devez générer un modèle relativement aléatoire, l'écrire sur le disque, lire et comparer la valeur. Il existe également des secteurs instables, qui changent leurs valeurs progressivement au fil du temps ou après traitement de ses voisins.


Compte tenu de tout ce qui précède, j'ai décidé de mettre en œuvre la stratégie suivante dans un script bash:


  • nous générons un modèle aléatoire et considérons la somme de contrôle pour cela;
  • nous lisons intelligemment;
  • écrire un disque en zéros;
  • lire le disque;
  • nous écrivons un disque de façon aléatoire en lisant le bloc qui vient d'être enregistré et en comparant sa somme de contrôle;
  • nous lisons le disque après l'enregistrement complet, en vérifiant les sommes de contrôle de chaque bloc;
  • nous lisons intelligemment;
  • auto-test;
  • goto 1.

Nous continuons ainsi jusqu'à ce que les secteurs mal lus et les erreurs d'E / S cessent de se produire ou jusqu'à ce que la vis soit complètement recouverte. Soit dit en passant, comment fonctionne l'autotest pour ce modèle de disque, je ne peux pas imaginer; Je ne sais pas combien de temps diffère de short'a (bien que probablement long avec toute la surface, et court - en se concentrant sur les statistiques précédemment collectées, comme avec le formatage: complet et rapide). J'espère que cela encourage la vis à prendre en compte les expériences récentes et à remapper les mauvais secteurs.


Quand j'ai fini d'écrire le script bash, je l'ai exécuté et vérifié les résultats le lendemain - j'ai vu que la vérification fonctionne très lentement, tandis que la charge du processeur n'atteint 60% sur aucun cœur. Cela m'a fait jouer avec la taille du bloc, tester différents algorithmes de hachage pour les sommes de contrôle, essayer la vérification directe des différences et ne pas comparer les sommes de contrôle, mais je n'ai pas pu atteindre des vitesses de traitement supérieures à 12 mégaoctets par seconde. En conséquence, je me suis arrêté à comparer des blocs de 400 Ko avec diff, et je ne calcule les sommes de contrôle qu'en cas de non-correspondance uniquement pour l'analyse ultérieure du journal.


Le script s'est avéré comme ceci:
 #!/bin/bash #    hddtest.sh diskdev logfile [blocksize] diskdev="$1"; test_log="$2"; #"~/work/hdd/test.log" blsz="${409600:-$3}"; n="1"; sizebyte=`fdisk -l "$diskdev"|grep "Disk $diskdev:"|cut -d" " -f5`; let sizebl=$sizebyte/$blsz; #"781428" for 320GB while true;do echo "starting iteration $n"; dd if=/dev/urandom of=fil bs="$blsz" count=1; md5ok=`md5sum fil|cut -d" " -f1`; cp fil fil_"$n"; echo "random pattern md5sum $md5ok">>"$test_log"; smartctl -A "$diskdev">>"$test_log"; echo "filling disk with zeroes">>"$test_log"; dd if=/dev/zero of="$diskdev" bs="$blsz"; #count="$sizebl"; echo "disk is wiped fully">>"$test_log"; dd of=/dev/null if="$diskdev" bs="$blsz"; # count="$sizebl"; echo "writing disk with fil-pattern">>"$test_log"; i="0"; while [ "$i" -le "$sizebl" ]; do #echo "writing fil: $i ">>"$test_log"; dd if=fil of="$diskdev" bs="$blsz" seek="$i"; dd if=/dev/null of=tst; dd if="$diskdev" bs="$blsz" of=tst skip="$i" count=1 conv=notrunc,noerror,sync; #md5tst=`md5sum tst|cut -d" " -f1`; verf=`diff -s fil tst|sed 's/.* //g'`; if [ "$verf" != "identical" ]; #if [ "$md5ok" != "$md5tst" ]; then md5tst=`md5sum tst|cut -d" " -f1`; echo "$i : md5 $md5tst is not ok">>"$test_log"; cp tst tst_"$n"_"$i"; fi; let i="$i"+1; done; echo "test of full writed with fil-pattern disk">>"$test_log"; i="0"; while [ "$i" -le "$sizebl" ]; do #echo "after writing test: $i">>"$test_log"; dd if=/dev/null of=tst; dd if="$diskdev" bs="$blsz" of=tst skip="$i" count=1 conv=notrunc,noerror,sync; #md5tst=`md5sum tst|cut -d" " -f1`; verf=`diff -s fil tst|sed 's/.* //g'`; if [ "$verf" != "identical" ]; #if [ "$md5ok" != "$md5tst" ]; then md5tst=`md5sum tst|cut -d" " -f1`; echo "$i : md5 $md5tst is not ok">>"$test_log"; cp tst tst_"$n"_"$i"; fi; let i="$i"+1; done; smartctl -A "$diskdev" >>"$test_log"; smartctl -t long "$diskdev">>"$test_log"; sleep 5000; #smartctl -t short "$diskdev">>"$test_log"; #sleep 240; let n="$n"+1; done 

Comme les journaux l'ont montré après l'exécution répétée du script, tous les secteurs défectueux se trouvaient dans les 13 premiers Go du disque, il y avait plusieurs "foyers" de défaite (probablement, lorsque la tête a frappé, la surface a été rayée et rayée). Pour les 15 dernières exécutions, le disque n'a pas vu de secteurs en attente, tout a déjà été remappé, mais quelque part au milieu du 13e gigaoctet, un bloc ou des blocs non loin de lui ont été lus de manière incorrecte à différentes adresses. De plus, un bloc peut être considéré comme incorrect pendant 2 cycles consécutifs, puis 2 fois correctement et encore incorrectement. Donc, attraper les 10 derniers secteurs défectueux a été une longue opération. Au total, 1268 secteurs ont été remappés! Et à la fin, une surprise m'attendait: lorsque tout fonctionnait déjà de manière stable, après le prochain autotest, le paramètre Nombre de secteurs réaffectés devenait "0" et seuls le Nombre d'événements réaffectés et les enregistrements des 5 dernières erreurs (avec adresse et heure à partir de commencer à travailler) stocké dans le journal.


Malgré le fonctionnement stable, j'ai néanmoins décidé de minimiser l'interaction avec la zone endommagée afin de ne pas blesser la tête sur d'éventuelles irrégularités dans des endroits avec une surface endommagée des plaques, et je ne voulais pas faire confiance aux secteurs locaux à long terme. Je viens de reculer un peu avec une marge et j'ai créé une partition commençant par le 15e gigaoctet. Et, comme le temps l'a montré, le disque se sent plutôt bien et fonctionne de manière stable dans un ordinateur portable portable depuis 10 mois.


Bien qu'il soit impossible de faire entièrement confiance au disque restauré et que la faisabilité économique de l'entreprise soit douteuse, le résultat n'est parfois qu'un ajout agréable à la bonne voie.

Source: https://habr.com/ru/post/fr481952/


All Articles