Como posso testar a capacidade total de um cartão SD no Linux?


17

Comprei um cartão SD de 64 GB no eBay. Funciona bem quando eu gravo uma imagem ARM do Arch Linux e a uso para inicializar meu Raspberry Pi.

No entanto, quando tento criar uma única partição ext4 para usar toda a capacidade do cartão, ocorrem erros. mkfs.ext4sempre termina feliz; no entanto, a partição não pode ser mounteditada, sempre gerando um erro e dmesgmostra inclusões nas mensagens do kernel Cannot find journal. Este provou ser o caso em pelo menos duas plataformas: Arch Linux ARM e Ubuntu 13.04.

Por outro lado, posso criar e montar uma partição FAT32 sem erros (uma verificação de capacidade total não foi feita).

Ouvi dizer que alguns bandidos podem mudar a interface do cartão SD para relatar uma capacidade incorreta ao sistema operacional (ou seja, o cartão tem realmente apenas 2 GB, mas se informa como 64 GB) para vender o cartão a um preço melhor.

Eu sei que badblocksexistem ferramentas como essa para eu verificar o cartão SD quanto a blocos defeituosos. Pode badblocksdetectar problemas como este? Caso contrário, que outras soluções existem para eu testar o cartão?

Idealmente, gostaria de saber se fui enganado ou não; se o resultado mostrar que acabei de receber um item com defeito, posso retornar apenas ao vendedor, em vez disso, informar ao eBay que alguém tentou me enganar.

ATUALIZAR

operações e mensagens:

~$ sudo mkfs.ext4 /dev/sde1
mke2fs 1.42.5 (29-Jul-2012)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
4096000 inodes, 16383996 blocks
819199 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=4294967296
500 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks: 
    32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
4096000, 7962624, 11239424

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done   

~$ dmesg | tail
...
[4199.749118]...
~$ sudo mount /dev/sde1 /mnt
mount: wrong fs type, bad option, bad superblock on /dev/sde1,
   missing codepage or helper program, or other error
   In some cases useful info is found in syslog - try
   dmesg | tail  or so

~$ dmesg | tail
...
[ 4199.749118]...
[ 4460.857603] JBD2: no valid journal superblock found
[ 4460.857618] EXT4-fs (sde1): error loading journal

ATUALIZAR

Eu executei, badblocks /dev/sdemas ele não relata erro. Isso significa que as causas restantes são:

  • O carro SD é bom, mas por algum motivo mke2fsou mountou o kernel tem um bug que causa o problema.

  • Fui enganado de uma maneira que badblocksnão pode detectar a derrota. Isso é plausível, porque eu acho que badblocksestá apenas fazendo algum teste de gravação / leitura no local. No entanto, o trapaceiro pode fazer o acesso às áreas de saída vincular de volta a algum bloco de entrada. Nesse caso, uma verificação de gravação / leitura no local não é capaz de detectar o problema.

Se não houver um aplicativo que possa fazer o teste adequado, acho que posso tentar escrever um programa C simples para testá-lo.


Você já tentou isso em um leitor de cartão SDXC USB?
Ignacio Vazquez-Abrams

Além disso, alguma mensagem aparece no log do sistema ao mesmo tempo que os erros?
Ignacio Vazquez-Abrams

Eu tentei tanto com o leitor de cartão Raspberry Pi nativo quanto com um leitor de cartão externo para o meu desktop Ubuntu. Eu disse que dmesgmostra as mensagens do kernel e tenho certeza de que elas aparecem ao mesmo tempo que os erros, porque eu fiz isso antes e depois e as comparei. Não verifiquei syslogporque acredito dmesgque mostrará as mensagens.
Earth Engine

Mostra outras mensagens?
Ignacio Vazquez-Abrams

O leitor de cartão externo que usei está funcionando para meus outros cartões, inclui cartões SDXC. No entanto, aquele problemático tem uma diferença: é um cartão micro SD com um adaptador SD.
Earth Engine

Respostas:



6

A trapaça agora foi confirmada pelas seguintes etapas:

  • Gere um arquivo de dados aleatórios. (4194304 = 4 × 1024 × 1024 = 4 MiB, tamanho total = 40 × 4 MiB = 160 MiB)

    Comando:

    dd if=/dev/urandom of=test.orig bs=4194304 count=40
    40+0 records in
    40+0 records out
    167772160 bytes (168 MB) copied, 11.0518 s, 15.2 MB/s
    
  • Copie os dados para o cartão SD. (2038340 × 4096 = 8153600 KiB = 7962,5 MiB)

    Comando:

    sudo dd if=test.orig of=/dev/sde seek=2038399 bs=4096
    40960+0 records in
    40960+0 records out
    167772160 bytes (168 MB) copied, 41.6087 s, 4.0 MB/s
    
  • Leia os dados novamente no cartão SD.

    Comando:

    sudo dd if=/dev/sde of=test.result skip=2038399 bs=4096 count=40960
    40960+0 records in
    40960+0 records out
    167772160 bytes (168 MB) copied, 14.5498 s, 11.5 MB/s
    
  • Mostrar o resultado

    Comando:

    hexdump test.result | less
    ...
    0000ff0 b006 fe69 0823 a635 084a f30a c2db 3f19
    0001000 0000 0000 0000 0000 0000 0000 0000 0000
    *
    1a81000 a8a5 9f9d 6722 7f45 fbde 514c fecd 5145
    
    ...
    

O que aconteceu? Observamos uma lacuna de zeros. Este é um indicador de que os dados aleatórios não foram realmente gravados no cartão. Mas por que os dados voltam depois 1a81000? Obviamente, o cartão tem um cache interno.

Também podemos tentar investigar o comportamento do cache.

hexdump test.orig | grep ' 0000 0000 '

não fornece resultado, o que significa que o lixo gerado não possui esse padrão. Contudo,

hexdump test.result | grep ' 0000 0000 '
0001000 0000 0000 0000 0000 0000 0000 0000 0000
213b000 0000 0000 0000 0000 0000 0000 0000 0000
407b000 0000 0000 0000 0000 0000 0000 0000 0000
601b000 0000 0000 0000 0000 0000 0000 0000 0000

tem 4 correspondências.

É por isso que passa no badblockscheque. Testes adicionais podem mostrar que a capacidade real é 7962,5 MB ou um pouco menos que 8 GB.

Concluo que é muito improvável que seja apenas uma falha aleatória de hardware, mas é mais provável que seja uma espécie de trapaça (isto é, fraude). Gostaria de saber que medidas posso tomar para ajudar outras vítimas.

Atualização 11/05/2019

  • As pessoas me perguntaram sobre como eu descobri o seekparâmetro correto 2038399. Eu tive muito mais experiência do que mostrei acima. Basicamente, você tem que adivinhar em primeiro lugar. Você precisa adivinhar um tamanho adequado de dados e adivinhar onde estava a corrupção dos dados. Mas você sempre pode usar o método de bissecção para ajudar.

  • No comentário abaixo, pensei que fosse assumido que o segundo passo acima (copiar os dados no cartão SD) copia apenas 1 setor. Mas não cometi esse erro em minha experiência. Em vez disso, seekera para mostrar que, na etapa "mostrar resultado", o deslocamento 1000é simplesmente acontecer no segundo setor dos dados. Se seekhouver 2038399 setores, a corrupção estará no 2038400º setor.


(1) De onde vêm os números 2038340 e 2038399? (2) Por que você usa  bs=4194304 count=40 ao ler, /dev/urandom mas   bs=4096 count=40960  ao gravar e ler no cartão SD? (Eles são matematicamente equivalente; 167772160 bytes cada.)
Scott

1) Usei a técnica bisec para descobrir o deslocamento. Como o procedimento bisec é muito detalhado para a resposta, eu simplesmente os coloco como uma evidência sem maiores explicações. 2) Sim, o cálculo é equivalente; mas não sei se devo corresponder ao tamanho do setor do cartão, que acredito ser 4096. #
Earth Engine

Ah, para o ponto 2) eu uso seek, então escrevi apenas 1 setor no cartão, o que economiza a quantidade de transferência de dados. É claro que, ao experimentar, usei blocos de dados maiores, é por isso que o arquivo de dados gerado é de 160MiB.
Earth Engine

Seu segundo comentário não faz nenhum sentido. O segundo comando na sua resposta - aquele que escreve no cartão - é sudo dd if=test.orig of=/dev/sde seek=2038399 bs=4096. E obviamente você está certo; ele usa seek. E, sim, tecnicamente, ele não usa count. ... (continua)
Scott

(Continua) ... Mas você diz: "Eu escrevi apenas 1 setor no cartão, o que economiza a quantidade de transferência de dados". Isso está claramente errado; sem uma countespecificação, ddtransfere toda a entrada (ou seja, transfere para EOF ou um erro). Portanto, esse comando transfere todo o conteúdo de test.orig, que é 40960 registros de 4096 bytes cada, para um total de 167772160 bytes (como eu disse).
1011 Scott

3

Antes de tudo, leia a resposta F3 de @Radtoo. É o caminho correto.

De alguma forma, senti falta disso e tentei do meu jeito:

  1. crie um arquivo de teste de 1 gb: dd if=/dev/urandom bs=1024k count=1024 of=testfile1gb

  2. escreva cópias desse arquivo no sdcard (64 é o tamanho do sdcard em gb): for i in $(seq 1 64); do dd if=testfile1gb bs=1024k of=/media/sdb1/test.$i; done

  3. verifique md5 de arquivos (todos, exceto o último, incompleto, devem corresponder): md5sum testfile1gb /media/sdb1/test.*


Essa é uma abordagem fácil e rápida.
Earth Engine


2

A maneira mais simples de testar a capacidade total de um cartão SD é preenchê-lo com arquivos e verificar se eles estão corretos: diff -qr /directory/on/computer /directory/on/SD

Como alternativa, você pode usar programas para gravar padrões ou cadeias de hashes em um arquivo e verificar se estão corretos.

Como @Earthy Engine apontou, é importante preencher o cartão SD e, em seguida, ler os dados, pois as abordagens tradicionais que simplesmente escrevem um pequeno bloco de dados e depois lêem são enganadas por cartões SSD falsos.


2

Eu escrevi um pequeno script que faz o seguinte.

-cria um diretório temporário para o cartão USB ou SC de destino

-cria um arquivo de referência gerado aleatoriamente 5MB com soma de verificação md5sum

-copia o arquivo de referência para o destino e gera uma verificação md5sum do destino para confirmar o sucesso de leitura / gravação

- preenche a capacidade de destino (100%) ou para quando ocorre um erro de soma de verificação

-se o script parar naturalmente, ele exibirá o tamanho alvo relatado, os valores Usado e Grátis.

Com este script, concluí que fui enganado por um vendedor do ebay que passou um microSD de 8 GB por um de 64 GB

#!/bin/bash
#Save file as 'filltext' and remember to set the executable flag to run it
if [ -d "$1" ]; then
 if [ -d "$1/tmp" ]; then
  echo "."
 else
  mkdir $1/tmp
 fi

#Make a tmp file and fill it with 3MB of junk
 TMPTSTR=$(mktemp)      
 base64 </dev/urandom  | head -c 5000000 > $TMPTSTR

 TESTVAL=$(md5sum $TMPTSTR | awk '{ print $1 }')

 while $CHECKEDOK; do

  FL=$( tr -dc A-Za-z0-9 </dev/urandom  | head -c 5).TEST

  cp $TMPTSTR $1/tmp/$FL
  TESTTMP=$(md5sum $1/tmp/$FL | awk '{ print $1 }')
  if [ "$TESTVAL" != "$TESTTMP" ]; then   
   echo "Checksum ERROR"
   echo "Original: $TESTVAL Temp File:$TESTTMP"
   CHECKEDOK=false
   df $1 -Ph
   echo 
   echo 
   echo "Removing test files"
   rm $1/tmp -r
   rm $TMPTSTR
   df $1 -Ph
  else
   #echo -n "$FL..."
   clear
   df $1 -Ph
  fi
 done

else
 echo "Error: Directory $1 does not exists."
 echo "Usage: filltest [PATH]"
 echo
 echo "Try the PATH of a mounted USB dongle or SD card to confirm it's capacity"

fi

1
Isso possivelmente dará resultados enganosos. Como o sistema de arquivos dos buffers do SO grava, você está testando principalmente a memória do sistema, não o cartão SD.
Cerin

a execução de "hdparm -W 0 / dev / disk" deve resolver um problema de gravação em buffer.
Michael

1

Pode-se escrever uma sequência de números (cada linha tem 16 bytes) e depois verificar o conteúdo:

dd if=<(seq -w 0 123456789012345) of=/dev/yourSdHere

Em seguida, verifique a saída skip == (usando uma pequena amostra dos valores de skip com menor número de registros gravados), por exemplo, skip = 9876 :

dd if=/dev/yourSdHere bs=16 count=1 skip=9876
000000000009876
1+0 records in
1+0 records out
16 bytes copied, ...

Ou faça uma amostra de 20 locais com um único revestimento:

seq -w 000000000000000 NumberOfWrittenRecords | shuf | head -20 | while read i; do [[ $(dd if=/dev/yourSdHere bs=16 count=1 skip=$i) == $i ]] && echo ok || echo bad; done
  • Verifique se você está escrevendo no cartão SD
  • Escreva em um arquivo of=tempFileOnSD, se você quiser evitar a destruição de dados armazenados no seu cartão (relevante apenas se não for falso)
  • No caso de um cartão de 8 GB rotulado como 64 GB, a chance de passar em todos os 20 testes é (8 GB / 64 GB) ** 20 <1e-18

1
Eu tive que ler sua resposta três vezes antes de entender o que você estava dizendo: "verificar pular == saída" não está claro. E, a menos que esteja faltando alguma coisa, sua abordagem exige que o usuário execute 123456789012345 e  inspecione manualmente a saída! Obviamente isso não é razoável. Por que não apenas fazer seq -w 0 123456789012345 > /dev/yourSdHeree seq -w 0 123456789012345 | cmp - /dev/yourSdHere?
675 Scott

Obrigado pelo comentário :) Eu editei minha resposta, espero que seja melhor agora!
karpada

Além disso, 123456789012345 é um número de 15 dígitos para fazer com que cada número use 16 bytes. pode-se usar o número de blocos de 16 bytes no SD
karpada
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.