Come posso testare la piena capacità di una scheda SD in Linux?


17

Ho acquistato una scheda SD da 64 GB da eBay. Funziona bene quando masterizzo un'immagine ARM di Arch Linux e la utilizzo per avviare il mio Raspberry Pi.

Tuttavia, quando provo a creare una singola partizione ext4 su di essa per utilizzare tutta la capacità della scheda, si verificano errori. mkfs.ext4finisce sempre felicemente; tuttavia, la partizione non può essere modificata mount, generando sempre un errore e dmesgmostrando che include i messaggi del kernel Cannot find journal. Questo ha dimostrato di essere il caso su almeno due piattaforme: Arch Linux ARM e Ubuntu 13.04.

D'altra parte, posso creare e montare una partizione FAT32 senza errori (non è stato eseguito un controllo della capacità totale).

Ho sentito che alcuni cattivi possono cambiare l'interfaccia della scheda SD per segnalare una capacità errata al sistema operativo (cioè la scheda è in realtà solo 2 GB ma si riferisce come 64 GB) al fine di vendere la scheda a un prezzo migliore.

So che badblocksesistono strumenti come me per controllare la scheda SD per blocchi danneggiati. Riesci a badblocksrilevare problemi come questo? In caso contrario, quali altre soluzioni esistono per provare la scheda?

Preferirei sapere se sono stato tradito o no; se il risultato mostra che ho appena ricevuto un articolo difettoso, posso tornare solo al venditore, piuttosto riferire a eBay che qualcuno ha cercato di imbrogliarmi.

AGGIORNARE

operazioni e messaggi:

~$ 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

AGGIORNARE

Ho eseguito badblocks /dev/sdema non riporta alcun errore. Ciò significa che le cause rimanenti sono:

  • La macchina SD è buono, ma per qualche motivo mke2fso mounto il kernel hanno un bug che causa il problema.

  • Sono stato ingannato in modo da badblocksnon poter rilevare la sconfitta. Questo è plausibile perché penso che badblocksstia solo facendo qualche test di lettura-scrittura sul posto. Tuttavia, il cheater può fare in modo che l'accesso alle aree in uscita sia ricollegato ad alcuni blocchi in entrata. In questo caso, un controllo di scrittura-lettura sul posto non è in grado di rilevare il problema.

Se non esiste un'applicazione in grado di eseguire il test corretto, penso di poter provare a scrivere un semplice programma C per testarlo.


L'hai provato in un lettore di schede USB SDXC?
Ignacio Vazquez-Abrams,

Inoltre, vengono visualizzati dei messaggi nel registro di sistema contemporaneamente agli errori?
Ignacio Vazquez-Abrams,

Ho provato sia con il lettore di schede Raspberry Pi nativo, sia con un lettore di schede esterno per il mio desktop Ubuntu. Ho detto che dmesgmostra i messaggi del kernel e sono sicuro che appare contemporaneamente agli errori perché l'ho fatto prima e dopo e li ho confrontati. Non ho controllato syslogperché credo dmesgmostrerà i messaggi.
Earth Engine,

Mostra altri messaggi?
Ignacio Vazquez-Abrams,

Il lettore di schede esterno che ho usato funziona con le altre mie carte, include le schede SDXC. Tuttavia quella problematica ha una differenza: è una scheda micro SD con un adattatore SD.
Earth Engine,

Risposte:


26

Se qualcuno lo vede più tardi: qualcuno ha scritto uno strumento open source chiamato "F3" per testare la capacità di schede SD e altri supporti di questo tipo. Può essere trovato sull'hompage del progetto e in Github .


In realtà è il riferimento in questo argomento per testare le schede SD ...
Philippe Gachoud,

6

Il trucco è stato ora confermato dai seguenti passaggi:

  • Genera un file di dati casuale. (4194304 = 4 × 1024 × 1024 = 4 MiB, dimensione totale = 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
    
  • Copia i dati sulla scheda 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
    
  • Rileggi i dati dalla scheda 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
    
  • Mostra il risultato

    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
    
    ...
    

Quello che è successo? Abbiamo osservato un divario di zeri. Questo è un indicatore del fatto che i dati casuali non sono stati effettivamente scritti sulla carta. Ma perché i dati tornano dopo 1a81000? Ovviamente la scheda ha una cache interna.

Possiamo anche provare a indagare sul comportamento della cache.

hexdump test.orig | grep ' 0000 0000 '

non fornisce alcun risultato, il che significa che la spazzatura generata non ha un tale schema. Tuttavia,

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

hanno 4 partite.

Quindi questo è il motivo per cui passa il badblockscontrollo. Ulteriori test possono mostrare che la capacità effettiva è 7962,5 MB, o leggermente inferiore a 8 GB.

Concludo che è molto improbabile che si tratti solo di un errore hardware casuale, ma è più probabile che si tratti di una sorta di imbroglio (ovvero frode). Vorrei sapere quale azione posso intraprendere per aiutare le altre vittime.

Aggiornamento 11/05/2019

  • La gente mi ha chiesto come ho capito che è il seekparametro corretto 2038399. Ho fatto molta più esperienza di quanto ho mostrato in precedenza. Fondamentalmente devi indovinare in primo luogo. Devi indovinare una dimensione dei dati adeguata e devi indovinare dove si trovava la corruzione dei dati. Ma puoi sempre usare il metodo di bisection per aiutarti.

  • Nel commento qui sotto ho pensato di presumere che il secondo passaggio sopra (copia i dati su scheda SD) copiasse solo 1 settore. Ma non ho fatto questo errore nel mio esperimento. Invece, è seekstato quello di mostrare che nel passaggio "Mostra risultato" l'offset 1000avviene semplicemente nel secondo settore dei dati. Se i seeksettori sono 2038399, la corruzione è al 2038400 ° settore.


(1) Da dove provengono i numeri 2038340 e 2038399? (2) Perché usi  bs=4194304 count=40 quando leggi /dev/urandom ma   bs=4096 count=40960  quando scrivi e leggi dalla scheda SD? (Sono matematicamente equivalenti; 167772160 byte ciascuno.)
Scott,

1) Ho usato la tecnica bisec per capire l'offset. Dato che la procedura bisec è troppo dettagliata per la risposta, la metto semplicemente in evidenza senza ulteriore denuncia. 2) Sì, il calcolo è equivalente; ma non so se dovrei corrispondere alla dimensione del settore della carta, che credo sia 4096.
Earth Engine

Oh, per il punto 2) lo uso seek, quindi ho scritto solo 1 settore sulla scheda, risparmiando la quantità di trasferimento dei dati. Di causa, durante la sperimentazione ho utilizzato blocchi di dati più grandi, ecco perché il file di dati generato è 160 MiB.
Earth Engine,

Il tuo secondo commento non ha alcun senso. Il secondo comando nella tua risposta - quello che scrive sulla carta - è sudo dd if=test.orig of=/dev/sde seek=2038399 bs=4096. E ovviamente hai ragione; usa seek. E, sì, tecnicamente, non lo usa count. ... (proseguendo)
Scott,

(Proseguendo) ... Ma tu dici "Ho scritto solo 1 settore sulla carta, il che consente di risparmiare la quantità di trasferimento di dati." È chiaramente sbagliato; senza una countspecifica, ddtrasferisce l'intero input (ovvero trasferisce fino a EOF o un errore). Quindi quel comando trasferisce l'intero contenuto di test.orig, che è 40960 record di 4096 byte ciascuno, per un totale di 167772160 byte (come ho detto).
Scott,

3

Prima di tutto, leggi la risposta F3 di @Radtoo. È il modo corretto

Mi è mancato in qualche modo e ho provato a modo mio:

  1. creare un file di test da 1 GB: dd if=/dev/urandom bs=1024k count=1024 of=testfile1gb

  2. scrivere copie di quel file su sdcard (64 ha le dimensioni di sdcard in gb): for i in $(seq 1 64); do dd if=testfile1gb bs=1024k of=/media/sdb1/test.$i; done

  3. controlla md5 di file (tutti tranne l'ultimo, incompleto, dovrebbero corrispondere): md5sum testfile1gb /media/sdb1/test.*


Questo è un approccio semplice e rapido.
Earth Engine,


2

Il modo più semplice per testare la piena capacità di una scheda SD è riempirlo con i file, quindi verificare che i file siano corretti: diff -qr /directory/on/computer /directory/on/SD

In alternativa, è possibile utilizzare i programmi per scrivere modelli o catene di hash in un file e quindi verificare che siano corretti.

Come ha sottolineato @Earthy Engine , è importante riempire la scheda SD, quindi leggere i dati, poiché gli approcci tradizionali che semplicemente scrivono un piccolo blocco di dati, quindi lo leggono, vengono ingannati da false schede SSD.


2

Ho scritto una piccola sceneggiatura che procede come segue.

-crea una directory temporanea sulla scheda USB o SC di destinazione

-crea un file di riferimento generato in modo casuale da 5 MB con checksum md5sum

-copia il file di riferimento sulla destinazione e genera un controllo md5sum dalla destinazione per confermare l'esito positivo della lettura / scrittura

riempie l'obiettivo fino alla capacità (100%) o si interrompe quando si verifica un errore di checksum

-una volta che lo script si interrompe in modo naturale, visualizza la dimensione di destinazione indicata, gli importi Utilizzato e Libero.

Con questo script ho concluso che sono stato derubato da un venditore ebay che ha passato una microSD da 8 GB per un 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
Questo probabilmente darà risultati fuorvianti. Poiché il filesystem del buffer del sistema operativo scrive, stai principalmente testando la memoria del tuo sistema, non la scheda SD.
Cerin,

l'esecuzione di "hdparm -W 0 / dev / disk" dovrebbe risolvere un problema di scrittura nel buffer.
Michael,

1

Si può scrivere una sequenza di numeri (ogni riga è di 16 byte) e quindi verificare il contenuto:

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

Quindi verifica skip == output (utilizzando un piccolo campione di valori skip che rappresentano un numero inferiore di record scritti) ad es. Skip = 9876 :

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

Oppure, crea un campione di 20 posizioni con un solo liner:

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
  • Assicurati di scrivere sulla scheda SD
  • Scrivi su un file of=tempFileOnSD, se vuoi evitare di distruggere i dati memorizzati sulla tua carta (rilevante solo se non è un falso)
  • Nel caso di una scheda da 8 GB etichettata come 64 GB, la possibilità di superare tutti i 20 test è (8 GB / 64 GB) ** 20 <1e-18

1
Ho dovuto leggere la tua risposta tre volte prima di capire cosa stavi dicendo: "verifica skip == output" non è chiaro. E, a meno che non mi manchi qualcosa, il tuo approccio richiede che l'utente esegua i comandi 123456789012345 e  controlli manualmente l'output! Ovviamente è irragionevole. Perché non farlo seq -w 0 123456789012345 > /dev/yourSdHeree seq -w 0 123456789012345 | cmp - /dev/yourSdHere?
Scott,

Grazie per il commento :) Ho modificato la mia risposta, spero sia meglio ora!
karpada,

Inoltre, 123456789012345 è un numero di 15 cifre per fare in modo che ciascun numero utilizzi 16 byte. si può usare il numero di blocchi di 16byte su SD
karpada
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.