Linux - Réparation de blocs défectueux sur une matrice RAID1 avec GPT

20

Le tl; dr: comment pourrais-je réparer un mauvais bloc sur 1 disque dans une matrice RAID1?

Mais veuillez lire tout cela pour ce que j'ai déjà essayé et les erreurs possibles dans mes méthodes. J'ai essayé d'être aussi détaillé que possible, et j'espère vraiment avoir des retours

Voici ma situation: j'ai deux disques de 2 To (même modèle) installés dans une matrice RAID1 gérée par mdadm. Il y a environ 6 mois, j'ai remarqué le premier mauvais bloc lorsque SMART l'a signalé. Aujourd'hui, j'ai remarqué plus et j'essaie maintenant de le réparer.

Cette page HOWTO semble être le seul article auquel tout le monde renvoie pour corriger les mauvais blocs signalés par SMART. C'est une excellente page, pleine d'informations, mais elle est assez obsolète et ne traite pas de ma configuration particulière. Voici comment ma configuration est différente:

  • Au lieu d'un disque, j'utilise deux disques dans une matrice RAID1. Un disque signale des erreurs tandis que l'autre va bien. Le HOWTO est écrit avec un seul disque à l'esprit, ce qui soulève diverses questions telles que «dois-je utiliser cette commande sur le périphérique de disque ou le périphérique RAID»?
  • J'utilise GPT, que fdisk ne prend pas en charge. J'ai utilisé gdisk à la place, et j'espère qu'il me donnera les mêmes informations dont j'ai besoin

Alors, allons-y. C'est ce que j'ai fait, mais cela ne semble pas fonctionner. N'hésitez pas à vérifier mes calculs et ma méthode pour les erreurs. Le disque signale des erreurs est / dev / sda:

# smartctl -l selftest /dev/sda
smartctl 5.42 2011-10-20 r3458 [x86_64-linux-3.4.4-2-ARCH] (local build)
Copyright (C) 2002-11 by Bruce Allen, http://smartmontools.sourceforge.net

=== START OF READ SMART DATA SECTION ===
SMART Self-test log structure revision number 1
Num  Test_Description    Status                  Remaining  LifeTime(hours)  LBA_of_first_error
# 1  Short offline       Completed: read failure       90%     12169         3212761936

Avec cela, nous comprenons que l'erreur réside sur LBA 3212761936. Suite au HOWTO, j'utilise gdisk pour trouver le secteur de démarrage à utiliser plus tard pour déterminer le numéro de bloc (car je ne peux pas utiliser fdisk car il ne prend pas en charge GPT):

# gdisk -l /dev/sda
GPT fdisk (gdisk) version 0.8.5

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with protective MBR; using GPT.
Disk /dev/sda: 3907029168 sectors, 1.8 TiB
Logical sector size: 512 bytes
Disk identifier (GUID): CFB87C67-1993-4517-8301-76E16BBEA901
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 3907029134
Partitions will be aligned on 2048-sector boundaries
Total free space is 2014 sectors (1007.0 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048      3907029134   1.8 TiB     FD00  Linux RAID

En utilisant tunefsje trouve que la taille du bloc est 4096. En utilisant ces informations et le calcul du HOWTO, je conclus que le bloc en question est ((3212761936 - 2048) * 512) / 4096 = 401594986.

Le HOWTO me demande ensuite debugfsde voir si le bloc est en cours d'utilisation (j'utilise le périphérique RAID car il a besoin d'un système de fichiers EXT, ce fut l'une des commandes qui m'a dérouté car je ne savais pas, au début, si je devais utiliser / dev / sda ou / dev / md0):

# debugfs
debugfs 1.42.4 (12-June-2012)
debugfs:  open /dev/md0
debugfs:  testb 401594986
Block 401594986 not in use

Le bloc 401594986 est donc un espace vide, je devrais pouvoir l'écrire sans problème. Avant d'écrire, cependant, j'essaie de m'assurer qu'il ne peut en effet pas être lu:

# dd if=/dev/sda1 of=/dev/null bs=4096 count=1 seek=401594986
1+0 records in
1+0 records out
4096 bytes (4.1 kB) copied, 0.000198887 s, 20.6 MB/s

Si le bloc ne pouvait pas être lu, je ne m'attendrais pas à ce que cela fonctionne. Mais c'est le cas. Je le répète , en utilisant /dev/sda, /dev/sda1, /dev/sdb, /dev/sdb1, /dev/md0et + -5 au numéro de bloc à rechercher autour du bloc défectueux. Tout fonctionne. Je hausse les épaules et j'avance et je valide l'écriture et la synchronisation (j'utilise / dev / md0 parce que je pensais que la modification d'un disque et non de l'autre pouvait causer des problèmes, de cette façon les deux disques écrasent le mauvais bloc):

# dd if=/dev/zero of=/dev/md0 bs=4096 count=1 seek=401594986
1+0 records in
1+0 records out
4096 bytes (4.1 kB) copied, 0.000142366 s, 28.8 MB/s
# sync 

Je m'attendrais à ce que l'écriture dans le mauvais bloc fasse que les disques réattribuent le bloc à un bon, mais l'exécution d'un autre test SMART montre différemment:

# 1  Short offline       Completed: read failure       90%     12170         3212761936

Retour à la case 1. Donc, fondamentalement, comment pourrais-je réparer un mauvais bloc sur 1 disque dans une matrice RAID1? Je suis sûr que je n'ai pas fait quelque chose correctement ...

Merci pour votre temps et votre patience.


EDIT 1:

J'ai essayé d'exécuter un long test SMART, avec le même LBA retourné comme mauvais (la seule différence est qu'il signale qu'il reste 30% au lieu de 90%):

SMART Self-test log structure revision number 1
Num  Test_Description    Status                  Remaining  LifeTime(hours)  LBA_of_first_error
# 1  Extended offline    Completed: read failure       30%     12180         3212761936
# 2  Short offline       Completed: read failure       90%     12170         3212761936

J'ai également utilisé des badblocks avec la sortie suivante. La sortie est étrange et semble mal formatée, mais j'ai essayé de tester les nombres sortis sous forme de blocs mais debugfs donne une erreur

# badblocks -sv /dev/sda
Checking blocks 0 to 1953514583
Checking for bad blocks (read-only test): 1606380968ne, 3:57:08 elapsed. (0/0/0 errors)
1606380969ne, 3:57:39 elapsed. (1/0/0 errors)
1606380970ne, 3:58:11 elapsed. (2/0/0 errors)
1606380971ne, 3:58:43 elapsed. (3/0/0 errors)
done
Pass completed, 4 bad blocks found. (4/0/0 errors)
# debugfs
debugfs 1.42.4 (12-June-2012)
debugfs:  open /dev/md0
debugfs:  testb 1606380968
Illegal block number passed to ext2fs_test_block_bitmap #1606380968 for block bitmap for /dev/md0
Block 1606380968 not in use

Je ne sais pas où aller d'ici. badblocksj'ai certainement trouvé quelque chose, mais je ne sais pas quoi faire des informations présentées ...


EDIT 2

Plus de commandes et d'informations.

Je me sens comme un idiot oubliant d'inclure cela à l'origine. Il s'agit des valeurs SMART pour /dev/sda. J'ai 1 Current_Pending_Sector et 0 Offline_Uncorrectable.

SMART Attributes Data Structure revision number: 16
Vendor Specific SMART Attributes with Thresholds:
ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE
  1 Raw_Read_Error_Rate     0x002f   100   100   051    Pre-fail  Always       -       166
  2 Throughput_Performance  0x0026   055   055   000    Old_age   Always       -       18345
  3 Spin_Up_Time            0x0023   084   068   025    Pre-fail  Always       -       5078
  4 Start_Stop_Count        0x0032   100   100   000    Old_age   Always       -       75
  5 Reallocated_Sector_Ct   0x0033   252   252   010    Pre-fail  Always       -       0
  7 Seek_Error_Rate         0x002e   252   252   051    Old_age   Always       -       0
  8 Seek_Time_Performance   0x0024   252   252   015    Old_age   Offline      -       0
  9 Power_On_Hours          0x0032   100   100   000    Old_age   Always       -       12224
 10 Spin_Retry_Count        0x0032   252   252   051    Old_age   Always       -       0
 11 Calibration_Retry_Count 0x0032   252   252   000    Old_age   Always       -       0
 12 Power_Cycle_Count       0x0032   100   100   000    Old_age   Always       -       75
181 Program_Fail_Cnt_Total  0x0022   100   100   000    Old_age   Always       -       1646911
191 G-Sense_Error_Rate      0x0022   100   100   000    Old_age   Always       -       12
192 Power-Off_Retract_Count 0x0022   252   252   000    Old_age   Always       -       0
194 Temperature_Celsius     0x0002   064   059   000    Old_age   Always       -       36 (Min/Max 22/41)
195 Hardware_ECC_Recovered  0x003a   100   100   000    Old_age   Always       -       0
196 Reallocated_Event_Count 0x0032   252   252   000    Old_age   Always       -       0
197 Current_Pending_Sector  0x0032   100   100   000    Old_age   Always       -       1
198 Offline_Uncorrectable   0x0030   252   100   000    Old_age   Offline      -       0
199 UDMA_CRC_Error_Count    0x0036   200   200   000    Old_age   Always       -       0
200 Multi_Zone_Error_Rate   0x002a   100   100   000    Old_age   Always       -       30
223 Load_Retry_Count        0x0032   252   252   000    Old_age   Always       -       0
225 Load_Cycle_Count        0x0032   100   100   000    Old_age   Always       -       77

# mdadm -D /dev/md0
/dev/md0:
        Version : 1.2
  Creation Time : Thu May  5 06:30:21 2011
     Raid Level : raid1
     Array Size : 1953512383 (1863.01 GiB 2000.40 GB)
  Used Dev Size : 1953512383 (1863.01 GiB 2000.40 GB)
   Raid Devices : 2
  Total Devices : 2
    Persistence : Superblock is persistent

    Update Time : Tue Jul  3 22:15:51 2012
          State : clean
 Active Devices : 2
Working Devices : 2
 Failed Devices : 0
  Spare Devices : 0

           Name : server:0  (local to host server)
           UUID : e7ebaefd:e05c9d6e:3b558391:9b131afb
         Events : 67889

    Number   Major   Minor   RaidDevice State
       2       8        1        0      active sync   /dev/sda1
       1       8       17        1      active sync   /dev/sdb1

Selon l'une des réponses: il semblerait que j'ai changé seeket skippour dd. J'utilisais la recherche car c'est ce qui est utilisé avec le HOWTO. L'utilisation de cette commande provoque ddle blocage: # dd if = / dev / sda1 of = / dev / null bs = 4096 count = 1 skip = 401594986

L'utilisation de blocs autour de celui-ci (..84, ..85, ..87, ..88) semble fonctionner très bien, et l'utilisation de / dev / sdb1 avec des blocs se 401594986lit également très bien (comme prévu car ce disque a passé les tests SMART ). Maintenant, la question que j'ai est la suivante: lorsque j'écris sur cette zone pour réaffecter les blocs, dois-je utiliser /dev/sda1ou /dev/md0? Je ne veux pas causer de problèmes avec la matrice RAID en écrivant directement sur un disque et en n'ayant pas l'autre mise à jour du disque.

EDIT 3

L'écriture dans le bloc a produit directement des erreurs de système de fichiers. J'ai choisi une réponse qui a rapidement résolu le problème:

# 1  Short offline       Completed without error       00%     14211         -
# 2  Extended offline    Completed: read failure       30%     12244         3212761936

Merci à tous ceux qui ont aidé. =)

blitzmann
la source
Vous avez pu lire le bloc, il n'est donc pas endommagé. Par conséquent, aucun secteur réaffecté. J'ai vérifié votre calcul de bloc fs et il semble légitime. Lorsque j'ai fait de mauvaises réaffectations de blocs, j'ai découvert que parfois un test court intelligent ne signalait pas correctement le bloc incriminé. Pendant ce temps, vous pouvez exécuter le long test hors ligne smartctl -t long /dev/sdaet voir si le LBA de la première erreur change.
Jari Laamanen
1
Essayez /sbin/badblocks -sv /dev/sdade vérifier le disque.
jippie
J'ai fait les deux suggestions et j'ai mis à jour le message en conséquence. Toujours coincé. = /
blitzmann
Smartctl signale-t-il un nombre Current_Pending_Sector non nul? Offline_Uncorrectable est-il différent de zéro?
mgorven
Veuillez ajouter l'état du tableau à la question:sudo mdadm -D /dev/md0
psusi

Réponses:

20

Toutes ces réponses «piquer le secteur» sont, franchement, folles. Ils risquent de corrompre le système de fichiers (éventuellement cachés). Si les données avaient déjà disparu, car ce disque stockait la seule copie, ce serait raisonnable. Mais il y a une très bonne copie sur le miroir.

Vous avez juste besoin que mdraid frotte le miroir. Il remarquera le mauvais secteur et le réécrira automatiquement.

# echo 'check' > /sys/block/mdX/md/sync_action    # use 'repair' instead for older kernels

Vous devez y mettre le bon appareil (par exemple, md0 au lieu de mdX). Cela prendra un certain temps, comme c'est le cas pour l'ensemble du tableau par défaut. Sur un noyau suffisamment nouveau, vous pouvez d'abord écrire des numéros de secteur dans sync_min / sync_max, pour le limiter à une partie seulement du tableau.

Il s'agit d'une opération sûre. Vous pouvez le faire sur tous vos appareils mdraid. En fait, vous devriez le faire régulièrement sur tous vos appareils mdraid. Votre distribution est probablement livrée avec un cronjob pour gérer cela, vous devez peut-être faire quelque chose pour l'activer?


Script pour tous les périphériques RAID du système

Il y a quelque temps, j'ai écrit ce script pour "réparer" tous les périphériques RAID du système. Cela a été écrit pour les anciennes versions du noyau où seule la «réparation» résoudrait le mauvais secteur; maintenant, il suffit de vérifier (la réparation fonctionne toujours bien sur les noyaux plus récents, mais elle recopie / reconstruit également la parité, ce qui n'est pas toujours ce que vous voulez, en particulier sur les lecteurs flash)

#!/bin/bash

save="$(tput sc)";
clear="$(tput rc)$(tput el)";
for sync in /sys/block/md*/md/sync_action; do
    md="$(echo "$sync" | cut -d/ -f4)"
    cmpl="/sys/block/$md/md/sync_completed"

    # check current state and get it repairing.
    read current < "$sync"
    case "$current" in
        idle)
            echo 'repair' > "$sync"
            true
            ;;
        repair)
            echo "WARNING: $md already repairing"
            ;;
        check)
            echo "WARNING: $md checking, aborting check and starting repair"
            echo 'idle' > "$sync"
            echo 'repair' > "$sync"
            ;;
        *)
            echo "ERROR: $md in unknown state $current. ABORT."
            exit 1
            ;;
    esac

    echo -n "Repair $md...$save" >&2
    read current < "$sync"
    while [ "$current" != "idle" ]; do
        read stat < "$cmpl"
        echo -n "$clear $stat" >&2
        sleep 1
        read current < "$sync"
    done
    echo "$clear done." >&2;
done

for dev in /dev/sd?; do
    echo "Starting offline data collection for $dev."
    smartctl -t offline "$dev"
done

Si vous voulez faire à la checkplace de repair, alors ce premier bloc (non testé) devrait fonctionner:

    case "$current" in
        idle)
            echo 'check' > "$sync"
            true
            ;;
        repair|check)
            echo "NOTE: $md $current already in progress."
            ;;
        *)
            echo "ERROR: $md in unknown state $current. ABORT."
            exit 1
            ;;
    esac
derobert
la source
Merci pour ça. Je suis récemment revenu sur ce problème en espérant enfin le résoudre. J'ai écrit dans le bloc / dev / md0 et j'ai eu des problèmes de système de fichiers, mais heureusement, après quelques heures de terreur et de démarrage dans des coquilles de récupération, tout était des réparations sans perte de données. J'essaierai d'abord votre méthode et j'espère que cela me débarrassera du secteur en attente. =)
blitzmann
Comment savoir quand le gommage est terminé? Est-ce que cat /sys/block/mdX/md/sync_actionlire « inactif » lorsque vous avez terminé?
Jon Cram
@JonCram oui, et vous pouvez regarder le statut par cat /proc/mdstatou si vous voulez l'écrire,/sys/…/sync_completed
derobert
5

Je viens d'avoir à peu près le même problème avec une matrice RAID1. Le mauvais secteur était au début d'une des partitions - le secteur 16 de / dev / sdb2. J'ai suivi les instructions ci-dessus: après avoir vérifié que le bloc logique 2 n'était pas utilisé par le système de fichiers et avoir pris soin de faire rechercher et ignorer dd dans le bon sens, et mettre à zéro 1 bloc du système de fichiers:

# dd if=/dev/zero of=/dev/md0 bs=4096 count=1 seek=2

Qu'est-ce que cela a fait? Cela n'a pas réglé le mauvais secteur. Ceci, je le sais maintenant, est dû au fait que / dev / md0 ne mappe pas directement sur / dev / sdb2, vous devez tenir compte du RAID DATA OFFSET! Plus d'informations ci-dessous. Ce qu'il a fait, c'est un petit mais potentiellement dévastateur sur mon système de fichiers. Il s'avère que le bloc logique 2 de / dev / md0 contenait des métadonnées de système de fichiers utiles et était correct sur les deux disques, jusqu'à ce que je craque sur les deux copies en écrivant dans / dev / md0. Heureusement, e2fsck -y / dev / md0 a résolu le problème (après avoir craché une quantité alarmante de sortie) sans perte apparente de données. Leçon apprise: si debugfs icheck dit «bloc non trouvé», cela ne signifie pas nécessairement que les secteurs correspondants ne sont pas utilisés.

Retour à l'offset de données: utilisez mdadm pour trouver l'offset comme ceci:

# mdadm --examine /dev/sdb2
/dev/sdb2:
          Magic : a92b4efc
        Version : 1.2
    Feature Map : 0x0
     Array UUID : ef7934b9:24696df9:b89ff03e:b4e5a05b
           Name : XXXXXXXX
  Creation Time : Sat Sep  1 01:20:22 2012
     Raid Level : raid1
   Raid Devices : 2

 Avail Dev Size : 1953241856 (931.38 GiB 1000.06 GB)
     Array Size : 976620736 (931.38 GiB 1000.06 GB)
  Used Dev Size : 1953241472 (931.38 GiB 1000.06 GB)
    Data Offset : 262144 sectors
   Super Offset : 8 sectors
          State : clean
    Device UUID : f3b5d515:446d4225:c2191fa0:9a9847b8

    Update Time : Thu Sep  6 12:11:24 2012
       Checksum : abb47d8b - correct
         Events : 54


    Device Role : Active device 0
    Array State : AA ('A' == active, '.' == missing)

Dans ce cas, le décalage de données est de 262144 secteurs de 512 octets. Si vous dd à partir de / dev / md0 et le comparez avec les données de la partition brute avec un décalage de 131072K, vous constaterez qu'elles correspondent. Donc dans mon cas, le bloc logique 2 (secteurs 16-23) de / dev / sdb2 n'est même pas dans le système de fichiers; ils sont dans le superbloc RAID, que vous pouvez lire ici: https://raid.wiki.kernel.org/index.php/RAID_superblock_formats - pour la version 1.2, il se compose de 256 octets + 2 octets par périphérique dans le tableau , tous démarrant à 4096 octets, donc dans mon cas, le mauvais secteur n'a pas été utilisé. Les secteurs correspondants de / dev / sdc2 (l'autre moitié de la matrice RAID1) sont nuls, donc je me suis dit que ce serait sûr de le faire:

# dd if=/dev/zero of=/dev/sdb2 bs=4096 count=1 seek=2

Ça a marché!

Samer
la source
OP ici. Merci pour cette information. Lorsque ce problème est apparu pour moi, j'ai fait le saut et mis le bloc à zéro au niveau / dev / md0. Mauvaise idée, car il m'est arrivé de perdre mon système de fichiers. Heureusement, après un temps de réparation impie, tout semblait bien sans perte de données. Mais avec la panique initiale, j'ai complètement oublié ce post. J'ai récemment installé mon serveur dans mon nouvel appartement, et c'est encore une fois une des choses sur ma liste de tâches, et je vous remercie pour votre compréhension du problème. Je mettrai à jour l'OP lorsque j'arriverai à creuser un peu plus. =)
blitzmann
2

Si vous exécutez Debian, vous avez très probablement un travail dans /etc/cron.d/mdadm. Cela se déroulera le /usr/share/mdadm/checkarray --cron --all --idle --quiet premier dimanche de chaque mois. Exécutez-le manuellement lorsque vous obtenez des erreurs matérielles non corrigibles pour accélérer la réécriture.

Håkon Alstadheim
la source
Eh bien, lorsque vous l'exécutez manuellement, vous voudrez probablement vous arrêter --cron.
derobert
1

Vous avez mélangé vos ddarguments. seekle fait rechercher le décalage spécifié dans la sortie . Vous vouliez skipbloquer sur l' entrée .

psusi
la source
Je vous remercie! J'ai mis à jour le message d'origine pour inclure les données de celui-ci. Si vous pouviez me dire comment réparer le blocage à partir d'ici, je pense que je vous accorderai une réponse. (Je ne sais pas si je devrais écrire directement /dev/sda1/ou utiliser /dev/md0pour écraser le bloc) =)
blitzmann
@Ryan, écrire à md0 devrait être le chemin à parcourir, bien que sda1 devrait également fonctionner.
psusi
0

Si vous avez un sw-raid1 et que vous écrivez des données directement à l'un des membres, vous aurez immédiatement un raid corrompu. N'écrivez PAS de données sur un sdaX ou sdbX si elles font partie d'un mdX. Si vous écrivez sur mdX, vous aurez les données copiées sur les deux disques, si vous lisez sur mdX, vous aurez les données lues sur l'un des disques.

Jose Tavares
la source