Ieri ho avuto un piccolo dibattito con qualcuno riguardo alla logica e / o alla veridicità della mia risposta qui , vis., Che registrare e mantenere i metadati dei fs su una scheda SD di dimensioni decenti (GB +) non potrebbe mai essere abbastanza significativo da indossare la scheda in un ragionevole lasso di tempo (anni e anni). La scia della contro-argomentazione sembrava essere che dovevo sbagliarmi dal momento che ci sono così tante storie online di persone che indossano schede SD.
Dal momento che ho dei dispositivi con schede SD contenenti file system root rw che vengono lasciati 24 ore su 24, 7 giorni su 7, ho già testato la premessa con mia grande soddisfazione. Ho modificato un po 'questo test, l'ho ripetuto (usando la stessa scheda, in effetti) e lo sto presentando qui. Le due domande centrali che ho sono:
- Il metodo che ho usato per tentare di distruggere la carta è praticabile, tenendo presente che è destinato a riprodurre gli effetti della riscrittura continua di piccole quantità di dati?
- Il metodo che ho usato per verificare che la scheda fosse ancora accettabile?
Sto ponendo la domanda qui piuttosto che SO o SuperUser perché un'obiezione alla prima parte dovrebbe probabilmente affermare che il mio test non ha davvero scritto sulla scheda nel modo in cui sono sicuro, e affermando che richiederebbe un po ' conoscenza speciale di linux.
[Potrebbe anche essere che le schede SD utilizzino un qualche tipo di buffer o cache intelligente, in modo tale che le scritture ripetute nello stesso posto vengano memorizzate / memorizzate nella cache in un luogo meno soggetto a usura. Non ho trovato alcuna indicazione di questo da nessuna parte, ma me lo sto chiedendo su SU]
L'idea alla base del test è di scrivere sullo stesso piccolo blocco sulla scheda milioni di volte. Questo va ben oltre ogni pretesa di quanti cicli di scrittura possono sostenere tali dispositivi, ma presumendo che il livellamento dell'usura sia efficace, se la carta è di dimensioni decenti, milioni di tali scritture non dovrebbero comunque importare molto, come farebbe "lo stesso blocco" non è letteralmente lo stesso blocco fisico. Per fare ciò, dovevo assicurarmi che ogni scrittura fosse realmente scaricata sull'hardware e nello stesso posto apparente .
Per scaricare l'hardware, ho fatto affidamento sulla chiamata alla libreria POSIX fdatasync()
:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
// Compile std=gnu99
#define BLOCK 1 << 16
int main (void) {
int in = open ("/dev/urandom", O_RDONLY);
if (in < 0) {
fprintf(stderr,"open in %s", strerror(errno));
exit(0);
}
int out = open("/dev/sdb1", O_WRONLY);
if (out < 0) {
fprintf(stderr,"open out %s", strerror(errno));
exit(0);
}
fprintf(stderr,"BEGIN\n");
char buffer[BLOCK];
unsigned int count = 0;
int thousands = 0;
for (unsigned int i = 1; i !=0; i++) {
ssize_t r = read(in, buffer, BLOCK);
ssize_t w = write(out, buffer, BLOCK);
if (r != w) {
fprintf(stderr, "r %d w %d\n", r, w);
if (errno) {
fprintf(stderr,"%s\n", strerror(errno));
break;
}
}
if (fdatasync(out) != 0) {
fprintf(stderr,"Sync failed: %s\n", strerror(errno));
break;
}
count++;
if (!(count % 1000)) {
thousands++;
fprintf(stderr,"%d000...\n", thousands);
}
lseek(out, 0, SEEK_SET);
}
fprintf(stderr,"TOTAL %lu\n", count);
close(in);
close(out);
return 0;
}
L'ho eseguito per ~ 8 ore, fino a quando non avevo accumulato 2 milioni + di scritture all'inizio della /dev/sdb1
partizione. 1 Avrei potuto facilmente usare /dev/sdb
(il dispositivo grezzo e non la partizione) ma non riesco a vedere che differenza farebbe.
Ho quindi controllato la scheda provando a creare e montare un filesystem su /dev/sdb1
. Funzionava, indicando che il blocco specifico a cui avevo scritto tutta la notte era fattibile. Tuttavia, ciò non significa che alcune regioni della carta non siano state consumate e spostate dal livellamento dell'usura, ma lasciate accessibili.
Per provarlo, ho usato badblocks -v -w
sulla partizione. Questo è un test distruttivo in lettura e scrittura, ma si consuma il livellamento o meno, dovrebbe essere una forte indicazione della fattibilità della scheda poiché deve comunque fornire spazio per ogni scrittura continua. In altre parole, è letteralmente l'equivalente di riempire completamente la carta, quindi verificare che tutto fosse a posto. Diverse volte, poiché ho lasciato che i badblock funzionassero attraverso alcuni schemi.
[Contro i commenti di Jason C di seguito, non c'è niente di sbagliato o di falso nell'usare i badblock in questo modo. Anche se non sarebbe utile per identificare effettivamente i blocchi danneggiati a causa della natura delle schede SD, va bene fare test distruttivi di lettura e scrittura di dimensioni arbitrarie usando gli switch -b
e -c
, che è dove è andato il test rivisto (vedi la mia risposta ). Nessuna quantità di magia o memorizzazione nella cache da parte del controller della scheda può ingannare un test in base al quale diversi megabyte di dati possono essere scritti su hardware e riletti correttamente. Gli altri commenti di Jason sembrano basati su una lettura errata: l'IMO è intenzionale , motivo per cui non mi sono preoccupato di discutere. Con quella testa in su, lascio al lettore la decisione su cosa abbia senso e cosa no .]
1 La scheda era una vecchia scheda Sandisk da 4 GB (non contiene un numero "di classe") che ho appena usato. Ancora una volta, tieni presente che questo non è 2 milioni di scritture nello stesso luogo fisico; a causa del livellamento dell'usura il "primo blocco" sarà stato spostato costantemente dal controller durante il test per, come afferma il termine, livellare l'usura.
/dev/sdb1
vs /dev/sdb
non fa alcuna differenza per il tuo programma, ma ciò che fa la differenza (come descritto di seguito) è che lo stato dei blocchi inutilizzati sul tuo dispositivo è sconosciuto e non è stato preso in considerazione nel tuo test e se non riempi l'intero dispositivo (ad es. /dev/sdb
) prima con i dati, la quantità di livellamento dell'usura dello spazio con cui lavorare è una variabile importante. Quindi, mentre dispositivo vs. partizione è irrilevante per il tuo test, ciò è principalmente una conseguenza di un test errato, poiché dopo aver riempito correttamente il dispositivo con i dati, per partizione non sarebbe un'opzione disponibile (a meno che tu non abbia formattato dopo).
badblocks
per mostrare errori di pagina su un'unità flash (e affermare che è molto fuorviante). Questi sono gestiti dal controller e mappati per riservare spazio quando rilevati. Il layout fisico dei dati sull'unità non è lo stesso del layout fisico che si vede quando si esegue l'I / O, ecco come il livellamento dell'usura mantiene la sua trasparenza. Niente di tutto ciò è visibile durante l'I / O. Al massimo, se l'unità supporta SMART, è possibile ottenere alcune informazioni sugli errori e lo spazio riservato rimanente dal controller.