Salta al contenuto principale

badblocks: cercare i blocchi difettosi di un disco

Inviato da tuxsa il

Un disco che comincia a dare errori di lettura, una chiavetta usata da anni o un disco usato appena comprato: prima di fidarsi dei propri dati può essere utile verificare che ogni settore risponda. Il comando classico per farlo, su Linux, è badblocks.

Cos'è

badblocks fa parte di e2fsprogs, lo stesso pacchetto di mkfs.ext4, e2fsck e tune2fs, ma non dipende dal tipo di file system: lavora direttamente sul dispositivo, e quindi funziona su una partizione, su un disco intero o su un file immagine. Non ripara nulla: il suo unico compito è scoprire quali blocchi non si leggono (o non mantengono ciò che vi si scrive) e riferirlo.

Cosa fa

Legge, o legge e scrive, tutti i blocchi del dispositivo uno dopo l'altro e stampa il numero di ogni blocco che dà errore. Ha tre modalità: una di sola lettura (la predefinita), una di lettura e scrittura non distruttiva (-n) e una di scrittura distruttiva (-w). L'elenco dei blocchi difettosi può essere salvato in un file e passato a mkfs o e2fsck, che lo usano per non assegnare mai quei blocchi ai file.

Come si usa

$ sudo badblocks [opzioni] DISPOSITIVO [ULTIMO [PRIMO]]

Gli ultimi due argomenti, facoltativi, limitano il controllo a un intervallo di blocchi, e vanno nell'ordine "ultimo, poi primo" (un'inversione rispetto a quello che ci si aspetta). Come negli articoli precedenti, negli esempi lavoro su un'immagine (d.img, 16 MB) per non toccare dischi veri; sul tuo sistema usa il dispositivo reale, ad esempio /dev/sdb. Un limite importante del mio banco di prova: un'immagine su un disco sano non ha blocchi difettosi, quindi tutti i test hanno trovato 0 errori. I messaggi che mostrano blocchi difettosi veri li descrivo ma non li ho potuti ottenere.

Esempio 1: il controllo base, in sola lettura

$ sudo badblocks -sv d.img
Checking blocks 0 to 16383
Checking for bad blocks (read-only test): done
Pass completed, 0 bad blocks found. (0/0/0 errors)

-s mostra l'avanzamento e -v i messaggi di stato. Senza -v il comando non stampa niente se non trova errori, e termina con codice 0: per questo conviene quasi sempre usarlo. Il numero di blocchi dipende dalla loro dimensione: con la dimensione predefinita (1024 byte) un'immagine da 16 MB ha 16384 blocchi, numerati da 0 a 16383. Nell'originale la riga di avanzamento viene riscritta sul posto, per cui nel terminale vedi una percentuale che sale; qui ho riportato solo il risultato finale.

Esempio 2: la dimensione del blocco

$ sudo badblocks -b 4096 -sv d.img
Checking blocks 0 to 4095
Checking for bad blocks (read-only test): done
Pass completed, 0 bad blocks found. (0/0/0 errors)

-b indica la dimensione del blocco in byte. I numeri stampati si riferiscono a quella dimensione: se poi vuoi usare l'elenco con mkfs.ext4 o e2fsck, devi usare lo stesso valore del file system (di solito 4096; lo trovi con tune2fs -l DEV | grep "Block size").

Esempio 3: controllare solo un intervallo

$ sudo badblocks -v d.img 100 50
Checking blocks 50 to 100
Checking for bad blocks (read-only test): done
Pass completed, 0 bad blocks found. (0/0/0 errors)

L'intervallo si scrive come "ultimo primo": qui 100 è l'ultimo e 50 il primo. Utile per riprovare una zona sospetta dopo un errore che il kernel ha segnalato (vedi dmesg).

Esempio 4: salvare l'elenco dei blocchi difettosi

$ sudo badblocks -b 4096 -o lista.txt d.img

-o scrive i numeri dei blocchi difettosi in un file, uno per riga. Su un disco sano il file resta vuoto (nel mio test pesava 0 byte). Il formato è semplicemente un numero per riga; non avendo blocchi difettosi veri, l'ho scritto a mano e verificato che mkfs.ext4 lo accetti:

$ cat lista.txt
100
101
2000

Esempio 5: usare l'elenco con mkfs.ext4

$ sudo mkfs.ext4 -b 4096 -l lista.txt d.img
$ sudo dumpe2fs -b d.img
dumpe2fs 1.47.0 (5-Feb-2023)
100
101
2000

L'opzione -l di mkfs.ext4 legge l'elenco e riserva quei blocchi, così nessun file li userà. dumpe2fs -b mostra l'elenco memorizzato nel file system. Qui l'ho provato con un elenco inventato su un'immagine, e ha funzionato; con blocchi realmente difettosi il discorso cambia (vedi in fondo). Per un file system esistente si usa e2fsck -l lista.txt DEV, che aggiunge i blocchi all'elenco ("Updating bad block inode"). In alternativa mkfs.ext4 -c esegue direttamente badblocks e usa il risultato.

Esempio 6: test non distruttivo

$ sudo badblocks -nsv -b 4096 n.img
Checking for bad blocks (non-destructive read-write test)
Testing with random pattern: done
Pass completed, 0 bad blocks found. (0/0/0 errors)

-n legge un blocco, ci scrive sopra dei dati di prova, li rilegge e poi rimette il contenuto originale. Il test è più accurato di quello di sola lettura e, in teoria, non perde dati. Nel mio test il checksum dell'immagine (md5sum) era identico prima e dopo, e il file system risultava ancora riconoscibile con blkid. Resta comunque rischioso su un disco malato: se il computer si spegne a metà, i dati di un blocco possono andare perduti. Il dispositivo non deve essere montato.

Esempio 7: test distruttivo di scrittura

$ sudo badblocks -wsv -b 4096 d.img
Checking for bad blocks in read-write mode
From block 0 to 4095
...
Pass completed, 0 bad blocks found. (0/0/0 errors)
$ blkid d.img
$ echo $?
2

-w scrive sul dispositivo una serie di schemi di prova e li rilegge. È il test più completo ma cancella tutto: nel mio test, dopo il comando blkid non riconosceva più nessun file system (nessun output e codice 2). Si usa su dischi nuovi o da riformattare, mai su dischi con dati. Con -t scegli lo schema (-t 0xaa, -t random) e con -p quante passate fare. Senza -t, da documentazione, il test usa quattro schemi in sequenza e richiede ore su un disco grande (non l'ho potuto cronometrare su un disco vero).

Esempio 8: uso negli script

#!/bin/bash
DEV="$1"
OUT=$(mktemp)
badblocks -b 4096 -o "$OUT" "$DEV" 2>/dev/null || {
    echo "test fallito su $DEV" >&2
    rm -f "$OUT"
    exit 2
}
n=$(wc -l < "$OUT")
rm -f "$OUT"
if [ "$n" -gt 0 ]; then
    echo "$DEV: $n blocchi difettosi" >&2
    exit 1
fi
echo "$DEV: nessun blocco difettoso"

Lo script fa un test in sola lettura e conta le righe del file di output: se ce ne sono, i blocchi difettosi sono tanti quante le righe. Sull'immagine sana stampa "nessun blocco difettoso" (codice 0); su un file inesistente dice "test fallito" (codice 2). Per provare il ramo dei blocchi difettosi ho messo nel PATH un finto badblocks che scrive due righe: lo script ha risposto "2 blocchi difettosi" con codice 1. Non fidarti del solo codice di uscita di badblocks: nel test su dischi sani è sempre 0 e non l'ho potuto verificare su dischi difettosi, per questo lo script conta le righe.

Opzioni utili

  • -v: messaggi dettagliati; -s: mostra l'avanzamento.
  • -b DIMENSIONE: dimensione del blocco in byte (usa quella del file system).
  • -o FILE: salva i blocchi difettosi in un file.
  • -i FILE: legge un elenco di blocchi già noti da saltare.
  • -n: test di lettura e scrittura non distruttivo.
  • -w: test di scrittura distruttivo.
  • -t SCHEMA: schema di prova (0xaa, random...); -p NUMERO: numero di passate.
  • -c BLOCCHI: quanti blocchi leggere alla volta; -e NUMERO: ferma il test dopo quel numero di errori.
  • -f: forza il test anche su un dispositivo che risulta montato (sconsigliato).

Attenzione a

  • -w cancella tutto: controlla due volte il nome del dispositivo con lsblk. Un errore di lettera distrugge il disco sbagliato.
  • Dispositivo smontato: i test di scrittura vanno fatti solo con il disco smontato.
  • Tempi lunghi: su un disco da qualche terabyte il test completo può richiedere ore o giorni. Lancialo in tmux o con nohup, così non si ferma se chiudi il terminale.
  • I dischi moderni si autoripristinano: hard disk e SSD rimappano da soli i settori difettosi, per cui un blocco difettoso che badblocks vede è già un segnale d'allarme. Prima di tutto guarda i dati SMART con smartctl.
  • Un blocco difettoso non si "ripara": sostituire il disco è quasi sempre la scelta giusta; l'elenco di mkfs -l serve a tamponare, non a risolvere.
  • Dimensione del blocco coerente: i numeri dell'elenco valgono solo con la dimensione usata da badblocks -b; se differisce da quella del file system, i blocchi esclusi sono quelli sbagliati.
  • Non è un controllo del file system: badblocks guarda l'hardware, non la coerenza dei file. Per quella serve fsck.

Riepilogo

ComandoCosa fa
badblocks -sv DEVTest in sola lettura con messaggi
badblocks -b 4096 -sv DEVTest con blocchi da 4 KiB
badblocks -v DEV 100 50Controlla solo i blocchi da 50 a 100
badblocks -o FILE DEVSalva l'elenco dei blocchi difettosi
badblocks -nsv DEVTest di lettura e scrittura non distruttivo
badblocks -wsv DEVTest di scrittura distruttivo
mkfs.ext4 -l FILE DEVCrea ext4 escludendo i blocchi elencati
e2fsck -l FILE DEVAggiunge blocchi difettosi a un file system
dumpe2fs -b DEVMostra i blocchi difettosi registrati