md raid5: traduce i numeri del settore interno md in offset


8

Riepilogo TL; DR : traduci un numero di settore md in offset (s) all'interno del /dev/mdXdispositivo e come investigarlo xfs_db. Il numero di settore proviene da sh->sectorin linux/drivers/md/raid5.c:handle_parity_checks5().

Non conosco gli interni MD, quindi non so esattamente cosa fare con l'output della printkregistrazione che ho aggiunto.

Anche gli offset nei dispositivi componenti (per ddo un editor / visualizzatore esadecimale) sarebbero interessanti.

Suppongo che dovrei chiederlo sulla mailing list del raid Linux. Sono solo abbonati o posso pubblicare senza abbonarmi?


Ho xfs direttamente sopra MD RAID5 di 4 dischi sul mio desktop (no LVM). Un recente scrub ha rilevato un valore diverso da zero mismatch_cnt(8 in effetti, perché md opera su pagine da 4 kB alla volta).

Questo è un RAID5, non RAID1 / RAID10 dove mismatch_cnt! = 0 può accadere durante il normale funzionamento . (Gli altri collegamenti in fondo a questa pagina wiki potrebbero essere utili ad alcune persone.)

Potrei solo ciecamente repair, ma poi non avrei idea di quale file verificare la possibile corruzione, oltre a perdere la possibilità di scegliere quale modo ricostruire. La risposta di Frostschutz a una domanda simile è l'unico suggerimento che ho trovato per risalire a una differenza nel filesystem. È ingombrante e lento, e preferirei usare qualcosa di meglio per restringerlo a pochi file prima.


Patch del kernel per aggiungere la registrazione

Stranamente, la funzione di controllo di md non segnala dove è stato trovato un errore . Ho aggiunto un printka md / raid5.c effettuare il login sh->sectornel iframo che incrementi mddev->resync_mismatchesinhandle_parity_checks5() (piccola toppa pubblicato su GitHub , originariamente basato sul 4.5-rc4 da kernel.org). Per questo per essere ok per uso generale, sarebbe probabilmente necessario evitare di inondare i registri nelle riparazioni con molte discrepanze (forse registrare solo se il nuovo valore di resync_mismatchesè <1000?). Inoltre forse accedi solo checke non repair.

Sono abbastanza sicuro che sto registrando qualcosa di utile (anche se non conosco gli interni MD!), Perché la stessa funzione stampa quel numero di settore nel caso di gestione degli errori diswitch .

Ho compilato il mio kernel modificato e avviato, quindi ho eseguito nuovamente il controllo:

[  399.957203] md: data-check of RAID array md125
...
[  399.957215] md: using 128k window, over a total of 2441757696k.
...
[21369.258985] md/raid:md125: check found mismatch at sector 4294708224    <-- custom log message
[25667.351869] md: md125: data-check done.

Ora non so esattamente cosa fare con quel numero di settore. C'è sh->sector * 512un indirizzo lineare all'interno /dev/md/t-r5(aka /dev/md125)? È un numero di settore all'interno di ciascun dispositivo componente (quindi fa riferimento a tre dati e un settore di parità)? Sto indovinando quest'ultimo, poiché una mancata corrispondenza di parità in RAID5 significa che i settori N-1 del dispositivo md sono in pericolo, compensati l'uno dall'altro dall'unità a strisce. Il settore 0 è l'inizio del dispositivo componente o è il settore dopo il superblocco o qualcosa del genere? Sono state fornite ulteriori informazioni handle_parity_checks5()che avrei dovuto calcolare / accedere?

Se volessi ottenere solo i blocchi non corrispondenti, è corretto?

dd if=/dev/sda6 of=mmblock.0 bs=512 count=8 skip=4294708224
dd if=/dev/sdb6 of=mmblock.1 bs=512 count=8 skip=4294708224
dd if=/dev/sda6 of=mmblock.2 bs=512 count=8 skip=4294708224
dd if=/dev/sdd  of=mmblock.3 bs=512 count=8 skip=4294708224  ## not a typo: my 4th component is a smaller full-disk

# i.e.
sec_block() { for dev in {a,b,c}6 d; do dd if=/dev/sd"$dev" of="sec$1.$dev"  skip="$1"  bs=512 count=8;done; }; sec_block 123456

Immagino di no, perché ottengo 4k di zeri da tutti e quattro i componenti del raid e 0^0 == 0, quindi, dovrebbe essere la parità corretta, giusto?

Un altro posto che ho visto menzionare l'uso di indirizzi di settore in md è for sync_mine sync_max(in sysfs). Neil Brown nella lista dei raid linux , in risposta a una domanda su un'unità guasta con numeri di settore da hdrecover, dove Neil ha usato il numero di settore del disco intero come numero di settore MD. Non è vero vero? I numeri di settore md non sarebbero relativi ai dispositivi componenti (partizioni in quel caso), non al dispositivo completo di cui fa parte la partizione?


settore lineare al nome file XFS:

Prima di rendermi conto che il numero del settore md era probabilmente per i componenti, non per il dispositivo RAID, ho provato a usarlo in sola lettura xfs_db:

Il brevissimo suggerimento di Dave Chinner su come scoprire come XFS sta usando un determinato blocco non sembra funzionare affatto per me. (Mi sarei aspettato un qualche tipo di risultato, per alcuni settori, poiché il numero non dovrebbe essere oltre la fine del dispositivo anche se non è il settore non corrispondente)

# xfs_db -r /dev/md/t-r5 
xfs_db> convert daddr 4294708224 fsblock
0x29ad5e00 (699227648)
xfs_db> blockget -nv -b 699227648
xfs_db> blockuse -n       # with or without -c 8
must run blockget first

eh? Cosa sto facendo di sbagliato qui? Immagino che questa dovrebbe essere una domanda separata. Lo sostituirò con un link se / quando lo chiedo o trovo una risposta a questa parte da qualche altra parte.

Il mio RAID5 è essenzialmente inattivo, senza attività di scrittura e lettura minima (e noatime, quindi le letture non producono scritture).


Altre cose sulla mia configurazione, niente di importante qui

Molti dei miei file sono video o altri dati compressi che forniscono un modo efficace per dire se i dati sono corretti o meno (o checksum interni nel formato file o semplicemente se decodifica senza errori). Ciò renderebbe possibile questo metodo di loopback di sola lettura , una volta che saprò quale file controllare. Non volevo eseguire una diff a 4 vie di ogni file nel filesystem per trovare prima la mancata corrispondenza, quando il kernel ha le informazioni necessarie durante il controllo e potrebbe facilmente registrarlo.


my /proc/mdstatper il mio array di dati di massa:

md125 : active raid5 sdd[3] sda6[0] sdb6[1] sdc6[4]
      7325273088 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/4] [UUUU]
      bitmap: 0/19 pages [0KB], 65536KB chunk

È su partizioni su tre unità Toshiba da 3 TB e su un'unità WD25EZRS a bassa potenza (lenta) non partizionata che sto sostituendo con un'altra Toshiba. (Usando mdadm --replaceper farlo online senza lacune nella ridondanza. Mi sono reso conto dopo una copia che avrei dovuto controllare lo stato RAID prima e dopo, per rilevare i problemi. È allora che ho rilevato la mancata corrispondenza. È possibile che sia in circolazione da molto tempo , dal momento che ho avuto alcuni crash quasi un anno fa, ma non ho vecchi registri e mdadm non sembra inviare messaggi su questo di default (Ubuntu 15.10).

I miei altri filesystem sono su dispositivi RAID10f2 realizzati da partizioni precedenti su tre HD più grandi (e RAID0 per / var / tmp). Il RAID5 è solo per l'archiviazione di massa, no /homeo /.

Le mie unità vanno bene: i conteggi degli errori SMART sono 0 tutti i contatori di blocchi danneggiati su tutte le unità e sono stati superati i test automatici SMART brevi + lunghi.


quasi duplicati di questa domanda che non hanno risposte:


Se il numero in printk è un settore relativo alla matrice, è necessario dividerlo per la larghezza della striscia e possibilmente aggiungere l'offset iniziale per convertirlo in un numero di settore relativo al dispositivo componente. iirc, se si utilizza un formato di metadati mdadm che non sempre avvia i dati a offset zero, l'offset da cui viene avviato viene elencato nell'output di mdadm -E /dev/xxx.
psusi,

Inoltre, tieni presente che anche se trovi la posizione dei dati e puoi verificare la mancata corrispondenza e hai un modo per controllare l'integrità del file danneggiato (se i dati appartengono anche a un file, potrebbe essere solo gratuito spazio o fs metadati), quindi è del tutto possibile e persino probabile che anche la parità sia errata e quindi nessuna delle possibili risposte che otterrete dal mascheramento di ciascuna unità di dati a sua volta sarà corretta.
psusi,

@psusi: grazie, sì, lo so che potrebbe non far parte di un file. Era difficile esprimerlo senza rendere le mie frasi davvero goffe. Punto interessante che forse nessuna delle ricostruzioni è corretta, sì, è possibile. Ad ogni modo, sarei molto più felice di sapere in quale file rinominare .damagedo qualcosa del genere, invece di sapere semplicemente che c'è probabilmente un file rotto da qualche parte.
Peter Cordes,

Risposte:


2

TL; DR sh-> sector è il numero di settori nei dischi fisici dopo l'inizio della sezione dati


Impostare

Ecco una semplice configurazione di prova per illustrare:

  • / dev / raidme / rd [0-3], dispositivi da 2 GB
  • / dev / md127 creato come raid5 su questi 5, avviato come xfs e pieno di dati casuali

Ora per iniziare, ottieni un blocco diverso da zero e sovrascriverlo

# dd if=/dev/raidme/rd0 bs=1k count=1 skip=10240 | hexdump -C | head
...
# dd if=/dev/zero of=/dev/raidme/rd0 bs=1k count=1 seek=10240
...
# dd if=/dev/raidme/rd2 bs=1k count=1 skip=10240 | hexdump  -C | head
1024 bytes (1.0 kB, 1.0 KiB) copied, 8.6021e-05 s, 11.9 MB/s
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000400

Assicurarsi che la cache dm / md sia svuotata arrestando / riassemblando l'array e controllare:

# mdadm --stop /dev/md127
# mdadm --assemble /dev/md127 /dev/raidme/rd*
# echo check > /sys/class/block/md127/md/sync_action
# dmesg | tail
...
[ 1188.057900] md/raid:md127: check found mismatch at sector 16384

Blocca su dischi

Ok, quindi prima controlliamo 16384 corrispondenze a quello che abbiamo scritto. Il mio raid ha una striscia di 512k, quindi mi sono assicurato di aver scritto qualcosa di allineato per essere facile da abbinare, abbiamo scritto su 1024*10240ie 0xa00000.

La tua patch fornisce le informazioni 16384, una cosa da tenere presente è che i dati non iniziano a 0:

# mdadm -E /dev/raidme/rd0 | grep "Data Offset"
    Data Offset : 4096 sectors

Quindi printf "%x\n" $(((4096+16384)*512))dice anche quello 0xa00000. Buona.


Blocco in md

Ora per arrivare dove si trova alla fine, è in realtà più semplice: è semplicemente la posizione indicata in tempi di settore, number_of_stripesad esempio per me ho 4 dischi (3 + 1) quindi 3 strisce.

Qui significa 16384*3*512ad es 0x1800000. Ho riempito il disco abbastanza bene, quindi è facile controllare solo leggendo il disco e cercando 1k di zero:

# dd if=/dev/md127 bs=1M | hexdump -C | grep -C 3 '00 00 00 00 00 00'
... some false positives...
01800000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
01800400  6b a8 9e e0 ad 88 a8 de  dd 2e 68 00 d8 7a a3 52  |k.........h..z.R|

Blocca in xfs

Freddo. Vediamo dove si trova ora xfs. 16384*3è 49152(daddr prende il numero di settore):

# xfs_db -r /dev/md127
xfs_db> blockget -n
xfs_db> daddr 49152
xfs_db> blockuse -n
block 6144 (0/6144) type data inode 2052 d.1/f.1

Sicuramente, gli zero sono in quel file:

# dd if=/mnt/d.1/f.1 bs=1M | hexdump -C | grep -C 3 '00 00 00 00 00'
...
03680000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
03680400  6b a8 9e e0 ad 88 a8 de  dd 2e 68 00 d8 7a a3 52  |k.........h..z.R|

Se sovrascriviamo quel file, gli zero vengono spostati in / dev / raidme / rd0 anche con l'offset corretto (basta averlo scaricato con un altro file). Se si scrive di nuovo in / dev / raidme / rd0 (assicurarsi di arrestare / riavviare l'array), gli zero tornano. Sembra buono.

C'è ancora un altro problema, se la tua dimensione della striscia è grande come la mia qui (512k), allora non abbiamo un solo blocco da gestire ma 1,5 MB di possibili dati danneggiati ... Spesso abbastanza che sarà in un file singolo, ma è necessario verificarlo, di nuovo in xfs_db. Ricorda che l'inode prima era il 2052.

xfs_db> inode 2052
xfs_db> bmap
data offset 0 startblock 256 (0/256) count 17536 flag 0
data offset 17536 startblock 122880 (0/122880) count 4992 flag 0
data offset 22528 startblock 91136 (0/91136) count 3072 flag 0

Un blocco ha dimensioni 4096 byte qui (vedi xfs_info), quindi i nostri 1,5 MB sono 384 blocchi. Il nostro segmento danneggiato è il blocco da 6144 a 6528, ben all'interno del primo segmento di questo file.

Qualcos'altro da guardare sarebbe quello di estrarre i blocchi a mano e controllare dove esattamente i checksum non corrispondono, il che si spera ti darà 3 pezzi più piccoli da guardare.


Infine per quanto riguarda la tua patch, non sono anch'io un md dev, ma come ex utente di mdadm raid5 sarei stato piuttosto interessato. Direi che vale sicuramente la pena spingerlo un po '. La pulizia che hai citato potrebbe essere utile e sono sicuro che gli sviluppatori avranno alcuni commenti una volta che avrai inviato una patch, ma diamine md deve essere più dettagliato su questi errori!


Eh, sono contento che tu abbia indicato la posizione sui dispositivi a blocchi sottostanti. Nel mio caso, printf '%#x\n' $(( (259072+4294708224 )*512 ))è 0x20000000000, che ovviamente non è una coincidenza. (Questo è esattamente 2TiB. Sospetto che alcuni shenanigans provengano da grub-install o da qualche tipo di cosa MBR). Non me ne sarei accorto se stavo solo osservando gli offset all'interno del dispositivo MD per trovare il file interessato. (A proposito, il %#xformato aggiunge il 0xprefisso per te.)
Peter Cordes,

xfs_dbdice solo must run blockget first, anche se l'ho appena fatto (esattamente come ho pubblicato nella domanda), dopo aver seguito il tuo esempio. Anche se lo uso blockget -v -n -b 12884124672per dargli un blocco specifico. Ho usato dde hexdumpper scoprire che c'è effettivamente una discrepanza in quel blocco, però. Tre sono tutti zero e il quarto ha un singolo bit impostato a 1 kB nella striscia da 512k. (Molto comodo che non ho dovuto trovare un modo per bloccare effettivamente i blocchi XOR per verificare la ridondanza.)
Peter Cordes,

Se uso daddrprima (prima di Blockget), non ricevo un messaggio di errore, ma nessun output da blockget -v -ne blockuse -v -n. Nel caso in cui sia importante, il mio xfsprogs è 3.2.1ubuntu1 e sto usando Linux 4.2.0-36-generico (non il mio kernel -rc con patch). Il mio FS sta usando crc=1 isize=512, naming =version 2 bsize=4096 ascii-ci=0 ftype=1
Peter Cordes, il

Ad ogni modo, questa risposta identifica correttamente la posizione del blocco di mancata corrispondenza sui dispositivi componenti e sul dispositivo md. L'unico pezzo che non funziona è il blocco XFS-> parte del nome file, che è in realtà una domanda separata. In teoria potrei usare find -exec xfs_bmap -vpl {} +per cercare un file contenente il blocco noto.
Peter Cordes,

1
Purtroppo non sono a conoscenza di alcun modo per fare in modo che xfs_db ignori il diario di registro (ad es. Forzare il blocco anche se non coerente al 100%), o per rendere il kernel "flush" quel registro come farebbe un umount / mount e rendere felice xfs_db. .. Quindi sì, a meno che tu non voglia kludge qualcosa, potrebbe essere necessario attendere un po 'prima di poter rimontare. Tienimi aggiornato e non dimenticare di provare a upstream quella patch :)
Asmadeus,
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.