¿Cómo puedo probar la capacidad total de una tarjeta SD en Linux?


17

Compré una tarjeta SD de 64 GB en eBay. Funciona bien cuando grabo una imagen ARM de Arch Linux y la uso para iniciar mi Raspberry Pi.

Sin embargo, cuando intento crear una única partición ext4 en ella para usar toda la capacidad de la tarjeta, se producen errores. mkfs.ext4siempre termina felizmente; sin embargo, la partición no se puede mounteditar, siempre arroja un error y dmesgmuestra los mensajes del núcleo incluidos Cannot find journal. Este ha demostrado ser el caso en al menos dos plataformas: Arch Linux ARM y Ubuntu 13.04.

Por otro lado, puedo crear y montar una partición FAT32 sin error (no se ha realizado una verificación de capacidad total).

Escuché que algunos tipos malos pueden cambiar la interfaz de la tarjeta SD para informar una capacidad incorrecta al sistema operativo (es decir, la tarjeta en realidad solo tiene 2 GB pero se reporta como 64 GB) para vender la tarjeta a un mejor precio.

Sé que badblocksexisten herramientas como para que compruebe que la tarjeta SD no tenga bloques defectuosos. ¿Puede badblocksdetectar problemas como este? Si no, ¿qué otras soluciones existen para que yo pruebe la tarjeta?

Idealmente me gustaría saber si fui engañado o no; Si el resultado muestra que acabo de recibir un artículo defectuoso, puedo volver solo al vendedor, en lugar de informar a eBay que alguien trató de engañarme.

ACTUALIZAR

operaciones y mensajes:

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

ACTUALIZAR

He corrido badblocks /dev/sdepero no informa ningún error. Eso significa que las causas restantes son:

  • La SD del coche es bueno, pero por alguna razón mke2fso mounto el núcleo tiene un error que causa el problema.

  • Fui engañado de una manera que badblocksno puede detectar la derrota. Esto es plausible porque creo que badblockssolo estoy haciendo una prueba de lectura y escritura en el lugar. Sin embargo, el tramposo puede hacer que el acceso a las áreas salientes se vincule a algún bloque entrante. En este caso, una comprobación de lectura y escritura in situ no puede detectar el problema.

Si no hay una aplicación que pueda hacer la prueba adecuada, creo que puedo intentar escribir un programa C simple para probarlo.


¿Lo has probado en un lector de tarjetas USB SDXC?
Ignacio Vázquez-Abrams

Además, ¿aparecen mensajes en el registro del sistema al mismo tiempo que los errores?
Ignacio Vázquez-Abrams

Probé tanto con el lector de tarjetas nativo de Raspberry Pi como también con un lector de tarjetas externo para mi escritorio Ubuntu. He dicho que dmesgmuestra los mensajes del kernel y estoy seguro de que aparece al mismo tiempo que los errores porque lo hice antes y después y los comparé. No lo he verificado syslogporque creo dmesgque mostrará los mensajes.
Earth Engine

¿Muestra algún otro mensaje?
Ignacio Vázquez-Abrams

El lector de tarjetas externo que utilicé funciona para mis otras tarjetas, incluye tarjetas SDXC. Sin embargo, esa problemática tiene una diferencia: es una tarjeta micro SD con un adaptador SD.
Earth Engine

Respuestas:



6

El engaño ahora ha sido confirmado por los siguientes pasos:

  • Generar un archivo de datos al azar. (4194304 = 4 × 1024 × 1024 = 4 MiB, tamaño total = 40 × 4 MiB = 160 MiB)

    Mando:

    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 los datos a la tarjeta SD. (2038340 × 4096 = 8153600 KiB = 7962.5 MiB)

    Mando:

    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
    
  • Lea los datos de la tarjeta SD.

    Mando:

    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 el resultado

    Mando:

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

¿Que pasó? Observamos una brecha de ceros. Este es un indicador de que los datos aleatorios no se han escrito realmente en la tarjeta. Pero, ¿por qué vuelven los datos después 1a81000? Obviamente la tarjeta tiene un caché interno.

También podemos intentar investigar el comportamiento del caché.

hexdump test.orig | grep ' 0000 0000 '

no proporciona ningún resultado, lo que significa que la basura generada no tiene ese patrón. Sin embargo,

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

Tiene 4 partidos.

Entonces es por eso que pasa el badblockscheque. Pruebas adicionales pueden mostrar que la capacidad real es 7962.5 MB, o un poco menos de 8 GB.

Concluyo que es muy poco probable que esto sea solo una falla aleatoria del hardware, pero es más probable que sea una especie de trampa (es decir, fraude). Me gustaría saber qué medidas puedo tomar para ayudar a otras víctimas.

Actualización 05/11/2019

  • La gente me preguntaba cómo descubrí el seekparámetro correcto 2038399. Hice mucha más experiencia de la que he mostrado en lo anterior. Básicamente tienes que adivinar en primer lugar. Debe adivinar un tamaño de datos adecuado y adivinar dónde estaba la corrupción de datos. Pero siempre puedes usar el método de bisección para ayudar.

  • En el comentario a continuación, pensé que se suponía que el segundo paso anterior (copiar los datos en la tarjeta SD) solo copia 1 sector. Pero no cometí este error en mi experiencia. En cambio, seekfue para mostrar que en el paso "mostrar resultado" el desplazamiento 1000simplemente ocurre en el segundo sector de los datos. Si los seeksectores son 2038399, la corrupción está en el sector 2038400.


(1) ¿De dónde vienen los números 2038340 y 2038399? (2) ¿Por qué usas  bs=4194304 count=40 cuando lees desde, /dev/urandom pero   bs=4096 count=40960  cuando escribes y lees desde la tarjeta SD? (Son matemáticamente equivalentes; 167772160 bytes cada uno.)
Scott,

1) Utilicé la técnica bisec para calcular el desplazamiento. Como el procedimiento bisec es demasiado detallado para la respuesta, simplemente los explico como evidentes sin más explicaciones. 2) Sí, el cálculo es equivalente; pero no sé si debería coincidir con el tamaño del sector de la tarjeta, que creo que es 4096.
Earth Engine

Ah, para el punto 2) Sí uso seek, así que solo escribí 1 sector en la tarjeta, lo que ahorra la cantidad de transferencia de datos. De hecho, al experimentar utilicé un bloque de datos más grande, por eso el archivo de datos generado es 160MiB.
Earth Engine

Tu segundo comentario no tiene ningún sentido. El segundo comando en su respuesta, el que escribe en la tarjeta, es sudo dd if=test.orig of=/dev/sde seek=2038399 bs=4096. Y obviamente tienes razón; que utiliza seek. Y, sí, técnicamente, no sirve count. ... (Continúa)
Scott

(Continúa) ... Pero usted dice "Solo escribí 1 sector en la tarjeta, lo que ahorra la cantidad de transferencia de datos". Eso es claramente incorrecto; sin uncount especificación, ddtransfiere toda la entrada (es decir, transfiere hasta EOF o un error). Entonces, ese comando transfiere todo el contenido de test.orig, que es 40960 registros de 4096 bytes cada uno, para un total de 167772160 bytes (como dije).
Scott

3

En primer lugar, lea la respuesta F3 de @Radtoo. Es el camino correcto.

De alguna manera lo extrañé e intenté a mi manera:

  1. crear archivo de prueba de 1 gb: dd if=/dev/urandom bs=1024k count=1024 of=testfile1gb

  2. escriba copias de ese archivo en la tarjeta sd (64 es el tamaño de la tarjeta sd en gb): for i in $(seq 1 64); do dd if=testfile1gb bs=1024k of=/media/sdb1/test.$i; done

  3. compruebe md5 de archivos (todos menos el último, incompleto, deben coincidir): md5sum testfile1gb /media/sdb1/test.*


Este es un enfoque fácil y rápido.
Earth Engine


2

La forma más sencilla de probar la capacidad total de una tarjeta SD es llenarla con archivos y luego verificar que los archivos sean correctos: diff -qr /directory/on/computer /directory/on/SD

Alternativamente, puede utilizar programas para escribir patrones o cadenas de hashes en un archivo y luego verificar que sean correctos.

Como señaló @Earthy Engine , es importante llenar la tarjeta SD, luego leer los datos, ya que los enfoques tradicionales que simplemente escriben un pequeño bloque de datos y luego los leen, son engañados por tarjetas SSD falsas.


2

Escribí un pequeño script que hace lo siguiente.

-crea un directorio temporal a la tarjeta USB o SC de destino

-crea un archivo de referencia de 5 MB generado aleatoriamente con suma de comprobación md5sum

-Copia el archivo de referencia al objetivo y genera una comprobación de md5sum desde el objetivo para confirmar el éxito de lectura / escritura

-llena el objetivo hasta su capacidad (100%) o se detiene cuando se produce un error de suma de comprobación

-una vez que el script se detiene de forma natural, muestra el tamaño objetivo indicado, las cantidades utilizadas y las cantidades gratuitas.

Con este script, llegué a la conclusión de que un vendedor de eBay me estafó y me pasó una microSD de 8GB por una de 64GB.

#!/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
Esto posiblemente dará resultados engañosos. Dado que el sistema operativo almacena temporalmente las escrituras del sistema de archivos, está probando principalmente la memoria de su sistema, no la tarjeta SD.
Cerin

la ejecución de "hdparm -W 0 / dev / disk" debería resolver un problema de escritura almacenado en el búfer.
Michael

1

Se puede escribir una secuencia de números (cada fila tiene 16 bytes) y luego verificar el contenido:

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

Luego verifique skip == output (usando una pequeña muestra de valores de skip que son un número menor de registros escritos) ej. Skip = 9876 :

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

O haga una muestra de 20 ubicaciones con un solo revestimiento:

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
  • Asegúrate de escribir en la tarjeta SD
  • Escriba en un archivo of=tempFileOnSD, si desea evitar destruir los datos almacenados en su tarjeta (relevante solo si no es falsa)
  • En el caso de una tarjeta de 8GB etiquetada como 64GB, la posibilidad de pasar las 20 pruebas es (8GB / 64GB) ** 20 <1e-18

1
Tuve que leer tu respuesta tres veces antes de entender lo que estabas diciendo: "verificar omitir == salida" no está claro. Y, a menos que me falte algo, su enfoque requiere que el usuario ejecute los comandos 123456789012345 e  inspeccione manualmente la salida. Obviamente eso no es razonable. ¿Por qué no solo hacer seq -w 0 123456789012345 > /dev/yourSdHerey seq -w 0 123456789012345 | cmp - /dev/yourSdHere?
Scott,

Gracias por el comentario :) He editado mi respuesta, ¡espero que sea mejor ahora!
karpada

Además, 123456789012345 es un número de 15 dígitos para hacer que cada número use 16 bytes. se puede utilizar el número de bloques de 16 bytes en la SD
karpada
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.