J'ai eu un petit débat avec quelqu'un hier concernant la logique et / ou la véracité de ma réponse ici , vis., Que la journalisation et la maintenance des métadonnées fs sur une carte SD de taille décente (GB +) ne pourraient jamais être suffisamment importantes pour porter la carte dans un délai raisonnable (années et années). L'essentiel du contre-argument semblait être que je dois me tromper car il y a tellement d'histoires en ligne de personnes utilisant des cartes SD.
Étant donné que j'ai des appareils avec des cartes SD contenant des systèmes de fichiers racine rw qui sont laissés en place 24 heures sur 24, 7 jours sur 7, j'avais testé le local avant à ma propre satisfaction. J'ai légèrement modifié ce test, je l'ai répété (en utilisant la même carte, en fait) et je le présente ici. Les deux questions centrales que j'ai sont:
- La méthode que j'ai utilisée pour tenter de détruire la carte est-elle viable, en gardant à l'esprit qu'elle est destinée à reproduire les effets d'une réécriture continue de petites quantités de données?
- La méthode que j'ai utilisée pour vérifier que la carte était toujours correcte est-elle viable?
Je pose la question ici plutôt que SO ou SuperUser car une objection à la première partie devrait probablement affirmer que mon test n'a pas vraiment écrit sur la carte comme je suis sûr qu'il le fait, et affirmer que cela nécessiterait une certaine connaissance particulière de linux.
[Il se peut également que les cartes SD utilisent une sorte de tampon ou de cache intelligent, de sorte que les écritures répétées au même endroit soient mises en mémoire tampon / mises en cache dans un endroit moins sujet à l'usure. Je n'ai trouvé aucune indication de cela nulle part, mais je pose la question à ce sujet sur SU]
L'idée derrière le test est d'écrire dans le même petit bloc sur la carte des millions de fois. C'est bien au-delà de toute affirmation du nombre de cycles d'écriture que ces appareils peuvent supporter, mais en supposant que le nivellement de l'usure est efficace, si la carte est d'une taille décente, des millions de telles écritures ne devraient toujours pas avoir beaucoup d'importance, comme le ferait le "même bloc". pas littéralement le même bloc physique. Pour ce faire, je devais m'assurer que chaque écriture était vraiment purgée sur le matériel et au même endroit apparent .
Pour le vidage sur le matériel, je me suis appuyé sur l'appel à la bibliothèque 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;
}
J'ai exécuté cela pendant environ 8 heures, jusqu'à ce que j'aie accumulé plus de 2 millions d'écritures au début de la /dev/sdb1
partition. 1 J'aurais pu facilement utiliser /dev/sdb
(le périphérique brut et non la partition) mais je ne vois pas quelle différence cela ferait.
J'ai ensuite vérifié la carte en essayant de créer et de monter un système de fichiers /dev/sdb1
. Cela a fonctionné, indiquant que le bloc spécifique sur lequel j'avais écrit toute la nuit était faisable. Cependant, cela ne signifie pas que certaines régions de la carte n'ont pas été usées et déplacées par le nivellement de l'usure, mais laissées accessibles.
Pour tester cela, j'ai utilisé badblocks -v -w
sur la partition. Il s'agit d'un test de lecture-écriture destructif , mais le nivellement par l'usure ou non, il devrait être une forte indication de la faisabilité de la carte car elle doit toujours fournir un espace pour chaque écriture continue. En d'autres termes, c'est l'équivalent littéral de remplir complètement la carte, puis de vérifier que tout cela allait bien. Plusieurs fois, car j'ai laissé les badblocks fonctionner à travers quelques modèles.
[Contra les commentaires de Jason C ci-dessous, il n'y a rien de mal ou de faux à utiliser les badblocks de cette façon. Bien qu'il ne soit pas utile d'identifier réellement les blocs défectueux en raison de la nature des cartes SD, il convient parfaitement pour effectuer des tests de lecture-écriture destructifs d'une taille arbitraire à l'aide des commutateurs -b
et -c
, qui est le test révisé (voir ma propre réponse ). Aucune quantité de magie ou de mise en cache par le contrôleur de la carte ne peut tromper un test par lequel plusieurs mégaoctets de données peuvent être écrits sur le matériel et relus correctement. Les autres commentaires de Jason semblent basés sur une mauvaise lecture - l'OMI est intentionnelle , c'est pourquoi je n'ai pas pris la peine de discuter. Avec cette tête haute, je laisse au lecteur le soin de décider ce qui a du sens et ce qui ne l'est pas .]
1 La carte était une ancienne carte Sandisk de 4 Go (elle n'a pas de numéro de "classe") que j'ai à peine utilisée. Encore une fois, gardez à l'esprit qu'il ne s'agit pas de 2 millions d'écritures au même endroit physique; en raison de la mise à niveau d'usure, le "premier bloc" aura été constamment déplacé par le contrôleur pendant le test pour, comme le terme l'indique, niveler l'usure.
/dev/sdb1
vs, /dev/sdb
cela ne fait aucune différence pour votre programme, mais ce qui fait la différence (comme décrit ci-dessous), c'est que l'état des blocs inutilisés sur votre appareil est inconnu et non pris en compte dans votre test, et à moins que vous ne remplissiez tout l'appareil (par exemple /dev/sdb
) avec les données en premier lieu, la quantité de nivellement d'usure de l'espace avec laquelle travailler doit être une variable majeure. Ainsi, alors que le périphérique par rapport à la partition n'est pas pertinent pour votre test, cela est principalement la conséquence d'un test défectueux, car après avoir correctement rempli le périphérique avec des données, la partition par partition ne serait pas une option disponible (sauf si vous avez formaté après).
badblocks
pour afficher les échecs de page sur un lecteur flash (et prétendre que c'est très trompeur). Celles-ci sont gérées par le contrôleur et mappées pour réserver de l'espace lorsqu'elles sont détectées. La disposition physique des données sur le lecteur n'est pas la même que la disposition physique que vous voyez lorsque vous effectuez des E / S, c'est ainsi que le niveau d'usure maintient sa transparence. Rien de tout cela n'est visible pour vous lors des E / S. Tout au plus, si le lecteur prend en charge SMART, vous pouvez obtenir des informations sur les pannes et l'espace réservé restant sur le contrôleur.