Linux: riparazione di blocchi danneggiati su un array RAID1 con GPT


20

Il tl; dr: come potrei fare per riparare un blocco danneggiato su 1 disco in un array RAID1?

Ma per favore leggi tutto per quello che ho già provato e possibili errori nei miei metodi. Ho cercato di essere il più dettagliato possibile e spero davvero di ricevere un feedback

Questa è la mia situazione: ho due dischi da 2 TB (stesso modello) configurati in un array RAID1 gestito da mdadm. Circa 6 mesi fa ho notato il primo blocco danneggiato quando SMART lo ha segnalato. Oggi ho notato di più e ora sto cercando di risolverlo.

Questa pagina dell'HOWTO sembra essere l'articolo a cui tutti collegano per correggere i blocchi danneggiati segnalati da SMART. È un'ottima pagina, piena di informazioni, tuttavia è abbastanza obsoleta e non risolve la mia particolare configurazione. Ecco come la mia configurazione è diversa:

  • Invece di un disco, sto usando due dischi in un array RAID1. Un disco segnala errori mentre l'altro va bene. L'HOWTO è scritto con un solo disco in mente, che solleva varie domande come "uso questo comando sul dispositivo disco o sul dispositivo RAID"?
  • Sto usando GPT, che fdisk non supporta. Ho usato invece gdisk e spero che mi stia fornendo le stesse informazioni di cui ho bisogno

Quindi, passiamo a questo. Questo è quello che ho fatto, tuttavia non sembra funzionare. Non esitate a ricontrollare i miei calcoli e il metodo per errori. Gli errori di segnalazione del disco sono / 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

Con questo, ci accorgiamo che l'errore risiede su LBA 3212761936. Seguendo l'HOWTO, uso gdisk per trovare il settore iniziale da utilizzare in seguito per determinare il numero di blocco (poiché non posso usare fdisk poiché non supporta 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

Usando tunefstrovo il blocco per essere 4096. Utilizzando queste informazioni e il calcolo dell'HOWTO, concludo che il blocco in questione è ((3212761936 - 2048) * 512) / 4096 = 401594986.

L'HOWTO mi indirizza quindi debugfsa vedere se il blocco è in uso (utilizzo il dispositivo RAID in quanto necessita di un filesystem EXT, questo è stato uno dei comandi che mi ha confuso in quanto all'inizio non sapevo se avrei dovuto usare / dev / sda o / dev / md0):

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

Quindi il blocco 401594986 è spazio vuoto, dovrei essere in grado di sovrascriverlo senza problemi. Prima di scriverlo, però, cerco di assicurarmi che, invero, non possa essere letto:

# 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

Se il blocco non potesse essere letto, non mi aspetto che funzioni. Tuttavia, lo fa. Ripeto utilizzando /dev/sda, /dev/sda1, /dev/sdb, /dev/sdb1, /dev/md0, e + -5 al numero di blocco per la ricerca intorno al blocco male. Funziona tutto Alzo le spalle e vado avanti e commetto la scrittura e la sincronizzazione (uso / dev / md0 perché ho pensato di modificare un disco e non l'altro potrebbe causare problemi, in questo modo entrambi i dischi sovrascrivono il blocco danneggiato):

# 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 

Mi aspetterei che scrivere sul blocco danneggiato avrebbe fatto sì che i dischi riassegnassero il blocco a un blocco buono, tuttavia l'esecuzione di un altro test SMART mostra diversamente:

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

Torna al quadrato 1. Quindi, in sostanza, come risolverei un blocco danneggiato su 1 disco in un array RAID1? Sono sicuro di non aver fatto qualcosa correttamente ...

Grazie per il tuo tempo e la tua pazienza.


MODIFICA 1:

Ho provato a eseguire un lungo test SMART, con lo stesso LBA che ha restituito un errore (l'unica differenza è che riporta il 30% rimanente anziché il 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

Ho anche usato i badblock con il seguente output. L'output è strano e sembra essere formattato in modo errato, ma ho provato a testare i numeri emessi come blocchi ma debugfs dà un errore

# 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

Non sono sicuro di dove andare da qui. badblockssicuramente trovato qualcosa, ma non sono sicuro di cosa fare con le informazioni presentate ...


MODIFICA 2

Più comandi e informazioni.

Mi sento un idiota che dimentica di includerlo in origine. Questi sono valori SMART per /dev/sda. Ho 1 Current_Pending_Sector e 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

Secondo una delle risposte: sembrerebbe che io abbia cambiato seeke skipper dd. Stavo usando la ricerca in quanto è ciò che viene utilizzato con l'HOWTO. L'uso di questo comando provoca il ddblocco: # dd if = / dev / sda1 di = / dev / null bs = 4096 count = 1 skip = 401594986

L'uso di blocchi attorno a quello (..84, ..85, ..87, ..88) sembra funzionare bene, e anche usare / dev / sdb1 con i blocchi 401594986legge bene (come previsto mentre quel disco ha superato i test SMART ). Ora, la domanda che ho è: quando scrivo su quest'area per riassegnare i blocchi, uso /dev/sda1o /dev/md0? Non desidero causare problemi con l'array RAID scrivendo direttamente su un disco e senza l'aggiornamento dell'altro disco.

MODIFICA 3

La scrittura sul blocco ha prodotto direttamente errori del file system. Ho scelto una risposta che ha risolto rapidamente il problema:

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

Grazie a tutti quelli che hanno aiutato. =)


Hai potuto leggere il blocco, quindi non è danneggiato. Quindi, nessun settore riallocato. Ho controllato il calcolo del tuo blocco fs e sembra legittimo. Quando ho effettuato riallocazioni di blocchi errate, ho scoperto che a volte i test brevi intelligenti non riportavano correttamente il blocco offensivo. Nel frattempo, puoi eseguire il lungo test offline smartctl -t long /dev/sdae vedere se l'LBA del primo errore cambia.
Jari Laamanen,

1
Prova /sbin/badblocks -sv /dev/sdaa controllare il disco.
jippie,

Ho fatto entrambi i suggerimenti e ho aggiornato il post di conseguenza. Ancora bloccato. = /
blitzmann il

Smartctl riporta un Current_Pending_Sector diverso da zero? Offline_Uncorrectable è diverso da zero?
mgorven

Aggiungi lo stato dell'array alla domanda:sudo mdadm -D /dev/md0
psusi

Risposte:


20

Tutte queste risposte "colpiscono il settore" sono, francamente, pazze. Rischiano la corruzione (possibilmente nascosta) del filesystem. Se i dati fossero già spariti, poiché quel disco memorizzava l'unica copia, sarebbe ragionevole. Ma c'è una copia perfettamente valida sullo specchio.

Hai solo bisogno di avere mdraid strofinare lo specchio. Noterà il settore danneggiato e lo riscriverà automaticamente.

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

Devi inserire il dispositivo giusto (es. Md0 invece di mdX). Questo richiederà un po 'di tempo, poiché per impostazione predefinita è l'intero array. Su un kernel abbastanza nuovo, è possibile scrivere prima i numeri di settore su sync_min / sync_max, per limitarlo solo a una parte dell'array.

Questa è un'operazione sicura. Puoi farlo su tutti i tuoi dispositivi mdraid. In effetti, dovresti farlo regolarmente su tutti i tuoi dispositivi mdraid. È probabile che la tua distribuzione venga fornita con un cronjob per gestire questo, forse devi fare qualcosa per abilitarlo?


Script per tutti i dispositivi RAID sul sistema

Qualche tempo fa, ho scritto questo script per "riparare" tutti i dispositivi RAID sul sistema. Questo è stato scritto per le versioni più vecchie del kernel in cui solo 'riparazione' avrebbe risolto il settore danneggiato; ora è sufficiente fare un controllo (la riparazione funziona ancora bene sui kernel più recenti, ma ri-copia / ricostruisce la parità, che non è sempre quello che vuoi, specialmente sulle unità 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

Se vuoi fare checkinvece di repair, allora questo primo blocco (non testato) dovrebbe funzionare:

    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

Grazie per questo. Di recente sono tornato a questo problema sperando di risolverlo finalmente. Ho scritto sul blocco / dev / md0 e ho avuto problemi con il filesystem, ma per fortuna dopo alcune ore di terrore e l'avvio in shell di ripristino tutto è stato riparato senza perdita di dati. Proverò prima il tuo metodo e spero che questo mi libererà dal settore in sospeso. =)
blitzmann,

Come puoi sapere quando lo scrub è completo? Leggerà cat /sys/block/mdX/md/sync_action"inattivo" al termine?
Jon Cram,

@JonCram sì, e puoi vedere lo stato di cat /proc/mdstato se vuoi /sys/…/sync_completed
scriverlo

5

Ho avuto praticamente lo stesso problema con un array RAID1. Il settore danneggiato era proprio all'inizio di una delle partizioni - settore 16 di / dev / sdb2. Ho seguito le istruzioni sopra: dopo aver verificato che il blocco logico 2 non era in uso dal file system e facendo attenzione a ottenere dd seek e saltare la strada giusta, azzerando 1 blocco del file system:

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

Che cosa ha fatto? Non ha riparato il settore difettoso. Questo, ora lo so, è perché / dev / md0 non esegue il mapping direttamente su / dev / sdb2, è necessario tenere conto dell'offset dei dati RAID! Maggiori informazioni su questo sotto. Quello che ha fatto è stato un piccolo ma potenzialmente devastante turd sul mio file system. Si scopre che il blocco logico 2 di / dev / md0 conteneva utili metadati del filesystem e andava bene su entrambi i dischi, finché non ho saltato su entrambe le copie scrivendo su / dev / md0. Fortunatamente, e2fsck -y / dev / md0 ha risolto il problema (dopo aver emesso una quantità allarmante di output) senza perdita apparente di dati. Lezione appresa: se il debugfs icheck dice "blocco non trovato", ciò non significa necessariamente che i settori corrispondenti non vengano utilizzati.

Torna all'offset dei dati: usa mdadm per trovare l'offset in questo modo:

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

In questo caso, l'offset dei dati è di 262144 settori di 512 byte. Se prendi da / dev / md0 e lo confronti con i dati della partizione non elaborata con un offset di 131072K, scoprirai che corrispondono. Quindi nel mio caso, il blocco logico 2 (settori 16--23) di / dev / sdb2 non è nemmeno nel file system; sono nel superblocco RAID, che puoi leggere qui: https://raid.wiki.kernel.org/index.php/RAID_superblock_formats - per la versione 1.2, è composto da 256 byte + 2 byte per dispositivo nell'array , tutti a partire da 4096 byte, quindi nel mio caso non è stato utilizzato il settore danneggiato. I settori corrispondenti di / dev / sdc2 (l'altra metà dell'array RAID1) sono zero, quindi ho pensato che sarebbe stato sicuro farlo:

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

Ha funzionato!


OP qui. Grazie per questa informazione. Quando questo problema si è presentato per me, ho fatto il salto e azzerato il blocco a livello / dev / md0. Pessima idea, visto che mi è capitato anche di schivare il mio filesystem. Per fortuna, dopo un ingente tempo di riparazione, tutto sembrava andare bene senza perdita di dati. Ma con il panico iniziale mi sono completamente dimenticato di questo post. Di recente ho installato il mio server nel mio nuovo appartamento, e questa è una delle cose sulla mia lista di cose da fare ancora una volta, e ti ringrazio per la tua comprensione del problema. Aggiornerò l'OP quando riesco a scavare un po 'di più. =)
blitzmann,

2

Se esegui debian, molto probabilmente hai un lavoro in /etc/cron.d/mdadm. Questo si svolgerà la /usr/share/mdadm/checkarray --cron --all --idle --quiet prima domenica di ogni mese. Eseguilo manualmente quando ricevi errori hardware non correggibili per accelerare la riscrittura.


Bene, quando lo esegui manualmente probabilmente vorrai smettere --cron.
derobert il

1

Hai confuso le tue ddargomentazioni. seekfa sì che cerchi l'offset specificato nell'output . Volevi skipbloccare sull'ingresso .


Grazie! Ho aggiornato il post originale per includere i dati da questo. Se potessi dirmi come risolvere il blocco da qui, penso che ti darò la risposta. (Non sono sicuro se dovrei scrivere direttamente /dev/sda1/o utilizzare /dev/md0per sovrascrivere il blocco) =)
blitzmann

@Ryan, scrivere su md0 dovrebbe essere la strada da percorrere, sebbene anche sda1 dovrebbe funzionare.
psusi,

0

Se si dispone di uno sw-raid1 e si scrivono dati direttamente a uno dei membri, si avrà immediatamente un raid corrotto. NON scrivere dati su sdaX o sdbX se fanno parte di un mdX. Se si scrive su mdX, i dati verranno copiati su entrambe le unità, se si legge da mdX, i dati verranno letti da una delle unità.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.