Ontem, entrei em um pequeno debate com alguém sobre a lógica e / ou veracidade da minha resposta aqui , vis., Que registrar e manter metadados fs em um cartão SD de tamanho decente (GB +) nunca poderia ser significativo o suficiente para usar o cartão em um período de tempo razoável (anos e anos). O ponto principal do contra-argumento parecia ser que eu devo estar errado, pois existem muitas histórias on-line de pessoas usando cartões SD.
Como eu tenho dispositivos com cartões SD contendo sistemas de arquivos raiz rw que permanecem 24/7, testei a premissa antes para minha própria satisfação. Ajustei um pouco esse teste, o repeti (usando o mesmo cartão, de fato) e estou apresentando aqui. As duas perguntas centrais que tenho são:
- O método que eu usei para tentar destruir o cartão é viável, tendo em mente que ele pretende reproduzir os efeitos da reescrita contínua de pequenas quantidades de dados?
- O método que eu usei para verificar se o cartão ainda era viável?
Estou colocando a pergunta aqui em vez de SO ou SuperUser, porque uma objeção à primeira parte provavelmente teria que afirmar que meu teste não foi realmente gravado no cartão da maneira que tenho certeza, e afirmar que exigiria alguma conhecimento especial do linux.
[Também pode ser que os cartões SD usem algum tipo de buffer ou cache inteligente, de modo que gravações repetidas no mesmo local sejam armazenadas em buffer / em cache em algum lugar menos propenso a serem desgastadas. Não encontrei nenhuma indicação disso em nenhum lugar, mas estou perguntando sobre isso no SU]
A idéia por trás do teste é escrever no mesmo pequeno bloco no cartão milhões de vezes. Isso está muito além de qualquer reivindicação de quantos ciclos de gravação esses dispositivos podem suportar, mas presumindo que o nivelamento de desgaste seja eficaz, se o cartão for de tamanho decente, milhões dessas gravações ainda não serão importantes, pois "o mesmo bloco" literalmente não seja o mesmo bloco físico. Para fazer isso, eu precisava garantir que todas as gravações fossem realmente liberadas para o hardware e para o mesmo local aparente .
Para liberar o hardware, contei com a chamada da biblioteca 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;
}
Eu executei isso por ~ 8 horas, até acumular mais de 2 milhões de gravações no início da /dev/sdb1
partição. 1 Eu poderia ter usado facilmente /dev/sdb
(o dispositivo bruto e não a partição), mas não consigo ver que diferença isso faria.
Em seguida, verifiquei o cartão tentando criar e montar um sistema de arquivos /dev/sdb1
. Isso funcionou, indicando que o bloco específico para o qual eu estava escrevendo a noite toda era viável. No entanto, isso não significa que algumas regiões do cartão não tenham sido desgastadas e deslocadas pelo nivelamento de desgaste, mas deixadas acessíveis.
Para testar isso, usei badblocks -v -w
na partição. Este é um teste de leitura e gravação destrutivo , mas com desgaste nivelado ou não, deve ser uma forte indicação da viabilidade do cartão, pois ele ainda deve fornecer espaço para cada gravação rotativa. Em outras palavras, é o equivalente literal de encher completamente o cartão e verificar se tudo estava bem. Várias vezes, desde que deixei os badblocks trabalharem em alguns padrões.
[Contra os comentários de Jason C abaixo, não há nada de errado ou falso em usar badblocks dessa maneira. Embora não seja útil para realmente identificar blocos defeituosos devido à natureza dos cartões SD, é bom fazer testes de leitura e gravação destrutivos de tamanho arbitrário usando as opções -b
e -c
, que é onde o teste revisado foi (veja minha própria resposta ) Nenhuma quantidade de mágica ou armazenamento em cache pelo controlador do cartão pode enganar um teste no qual vários megabytes de dados podem ser gravados no hardware e lidos novamente corretamente. Os outros comentários de Jason parecem baseados em uma leitura errada - a OMI é intencional , e é por isso que não me preocupei em discutir. Com essa ideia, deixo ao leitor decidir o que faz sentido e o que não faz .]
1 O cartão era um cartão Sandisk antigo de 4 GB (não possui um número de "classe") que eu mal usei. Mais uma vez, lembre-se de que não são 2 milhões de gravações no mesmo local físico; devido ao nivelamento do desgaste, o "primeiro bloco" será movido constantemente pelo controlador durante o teste para, como afirma o termo, nivelar o desgaste.
/dev/sdb1
vs, /dev/sdb
não faz diferença para o seu programa, mas o que faz diferença (como descrito abaixo) é que o estado dos blocos não utilizados no seu dispositivo é desconhecido e inexplicado no seu teste, e a menos que você preencha todo o dispositivo (por exemplo, /dev/sdb
) com os dados primeiro, a quantidade de nivelamento de desgaste de espaço com a qual trabalhar é uma variável importante. Portanto, embora o dispositivo x partição seja irrelevante para o seu teste, isso é principalmente uma consequência de um teste defeituoso, pois após o preenchimento correto do dispositivo com dados, a partição por partição não seria uma opção disponível (a menos que você tenha formatado depois).
badblocks
para mostrar falhas de página em uma unidade flash (e alegar que isso é muito enganador). Esses são manipulados pelo controlador e mapeados para reservar espaço quando detectados. O layout físico dos dados na unidade não é o mesmo que você vê ao realizar E / S, é assim que o nivelamento de desgaste mantém sua transparência. Nada disso é visível para você durante a E / S. No máximo, se a unidade oferecer suporte ao SMART, você poderá obter algumas informações sobre falhas e espaço reservado restante do controlador.