Cómo arreglar / reparar bloques defectuosos en Linux
Los bloques defectuosos en un dispositivo de almacenamiento son las partes del dispositivo que no se pueden leer por alguna razón. Estos badblocks se pueden recuperar si podemos llegar a la ubicación exacta de ese bloque.
La tecnología SMART incorporada en muchos dispositivos de almacenamiento (como muchos discos duros ATA-3, luego ATA, IDE y SCSI-3) monitorea la confiabilidad del disco duro y puede predecir fallas del disco. SMART significa tecnología de autocontrol, análisis e informes.
Este tutorial describe las acciones que se pueden tomar cuando smartmontools detecta y reporta algunos badblocks en el disco duro que ejecuta Linux.
Acerca de Smartmontools
El paquete smartmontools proporciona dos utilidades: smartrd y smartctl.
smartd es el demonio que sondea los dispositivos ATA y SCSI cada 30 minutos (este valor se puede cambiar) y registra los errores SMART y los cambios en los atributos SMART utilizando la interfaz SYSLOG.
El smartctl realiza tareas SMART y se puede utilizar para imprimir autodiagnósticos SMART y registros de errores, entre otras tareas, como la compatibilidad con el sondeo de mensajes TapeAlert desde unidades de cinta SCSI. El uso de este comando quedará claro a medida que avancemos en este artículo. Este artículo analiza algunos ejemplos de fallas de disco para diferentes tipos de sistemas de archivos.
comando smartctl
El comando smartctl informa un badblock en la dirección del bloque lógico LBA = 0x016561e9 que en el sistema numérico decimal es 23421417.
root]# smartctl -l selftest /dev/hda SMART Self-test log structure revision number 1 Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error # 1 Extended offline Completed: read failure 90% 217 0x016561e9
El LBA cuenta los sectores en unidades de 512 bytes a partir de cero. El valor del atributo «Current_Pending_Sector» en el comando «smartctl -A» confirma el sector defectuoso.
root]# smartctl -A /dev/hda ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE 5 Reallocated_Sector_Ct 0x0033 100 100 005 Pre-fail Always - 0 196 Reallocated_Event_Count 0x0032 100 100 000 Old_age Always - 0 197 Current_Pending_Sector 0x0022 100 100 000 Old_age Always - 1 198 Offline_Uncorrectable 0x0008 100 100 000 Old_age Offline - 1
Arreglar badblocks
Paso 1:
Busque la partición en la que reside el bloque defectuoso. El comando fdisk se puede utilizar para ver los sectores de las particiones del disco duro.
root]# fdisk -lu /dev/hda Disk /dev/hda: 123.5 GB, 123522416640 bytes 255 heads, 63 sectors/track, 15017 cylinders, total 241254720 sectors Units = sectors of 1 * 512 = 512 bytes Device Boot Start End Blocks Id System /dev/hda1 * 63 4209029 2104483+ 83 Linux /dev/hda2 4209030 5269319 530145 82 Linux swap /dev/hda3 5269320 238227884 116479282+ 83 Linux /dev/hda4 238227885 241248104 1510110 83 Linux
Aquí podemos ver que el LBA 23421417 se encuentra en la tercera partición, es decir, / dev / hda3. El valor de compensación del sector es 23421417 – 5269320 = 18152097 sectores en la partición / dev / hda3.
Ahora necesitamos verificar el tipo de sistema de archivos de la partición. Esto se puede comprobar en el archivo / etc / fstab.
root]# grep hda3 /etc/fstab /dev/hda3 /data ext2 defaults 1 2
Paso 2:
Ahora necesitamos encontrar el tamaño de bloque del sistema de archivos usando el comando tune2fs
root]# tune2fs -l /dev/hda3 | grep Block Block count: 29119820 Block size: 4096
Esto informa que el tamaño del bloque es de 4096 bytes.
Paso 3:
Busque el bloque del sistema de archivos que contiene este LBA problemático. Usamos la siguiente fórmula:
b = (int) ((LS) * 512 / B)
dónde:
b = número de bloque del sistema de archivos
B = Tamaño del bloque del sistema de archivos en bytes
L = LBA del sector defectuoso
S = Sector de inicio de la partición como se muestra en fdisk -lu
e (int) denota la parte entera.
Para nuestro ejemplo, L = 23421417, S = 5269320 y B = 4096.
b = (int) 18152097 * 512/4096 = (int) 2269012.125
entonces b = 2269012.
Paso 4:
Use debugfs para ubicar el inodo almacenado en este bloque y, por lo tanto, el archivo que está almacenado en esa ubicación.
root]# debugfs debugfs 1.32 (09-Nov-2002) debugfs: open /dev/hda3 debugfs: testb 2269012 Block 2269012 not in use
Aquí, en este caso, el bloque no está en uso. Entonces, el resto de este paso se puede omitir y podemos saltar directamente al siguiente paso. De lo contrario, si el bloque está en uso, según lo informado por la siguiente salida:
debugfs: testb 2269012 Block 2269012 marked in use debugfs: icheck 2269012 Block Inode number 2269012 41032 debugfs: ncheck 41032 Inode Pathname 41032 /S1/R/H/714197568-714203359/H-R-714202192-16.gwf
En este caso, el archivo problemático es: /data/S1/R/H/714197568-714203359/HR-714202192-16.gwf
En el caso del sistema de archivos ext3, este bloque puede ser parte de la propia revista. El inodo será muy pequeño y debugfs no podrá informar ningún nombre de archivo.
debugfs: testb 2269012 Block 2269012 marked in use debugfs: icheck 2269012 Block Inode number 2269012 8 debugfs: ncheck 8 Inode Pathname debugfs:
En este caso, podemos eliminar el diario con el comando tune2fs:
tune2fs -O ^has_journal /dev/hda3
Ahora, repetimos el paso 4, y si el problema ya no se informa, podemos reconstruir el diario:
tune2fs -j /dev/hda3
Paso 5:
Este paso destruirá los datos de ese bloque escribiendo ceros en él. El bloque defectuoso se recuperará pero se perderán los datos del archivo. Si está seguro, puede continuar con el siguiente paso:
root]# dd if=/dev/zero of=/dev/hda3 bs=4096 count=1 seek=2269012 root]# sync
Ahora podemos volver a comprobar la salida «smartctl -A» para verificar que todo ha vuelto a la normalidad.
root]# smartctl -A /dev/hda ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE 5 Reallocated_Sector_Ct 0x0033 100 100 005 Pre-fail Always - 1 196 Reallocated_Event_Count 0x0032 100 100 000 Old_age Always - 1 197 Current_Pending_Sector 0x0022 100 100 000 Old_age Always - 0 198 Offline_Uncorrectable 0x0008 100 100 000 Old_age Offline - 1
Aquí puede ver que el valor de «Current_Pending_Sector» es cero.
Error inteligente en Ext2 / ext3
To: ballen Subject: SMART error (selftest) detected on host: medusa-slave166.medusa.phys.uwm.edu This email was generated by the smartd daemon running on host: medusa-slave166.medusa.phys.uwm.edu in the domain: master001-nis The following warning/error was logged by the smartd daemon: Device: /dev/hda, Self-Test Log error count increased from 0 to 1
Este correo electrónico de smartd muestra la primera señal de problemas. Como se mencionó en el ejemplo anterior, ejecutamos «smartctl -a / dev / hda» para confirmar el problema:
Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error # 1 Extended offline Completed: read failure 80% 682 0x021d9f44
El LBA informado es 0x021d9f44 (base 16) = 35495748 (base 10)
ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE 5 Reallocated_Sector_Ct 0x0033 100 100 005 Pre-fail Always - 0 196 Reallocated_Event_Count 0x0032 100 100 000 Old_age Always - 0 197 Current_Pending_Sector 0x0022 100 100 000 Old_age Always - 3 198 Offline_Uncorrectable 0x0008 100 100 000 Old_age Offline - 3
Aquí, 3 sectores son ilegibles. Usando el siguiente script bash, podemos verificar los sectores alrededor de esa área.
[root]# export i=35495730 [root]# while [ $i -lt 35495800 ] > do echo $i > dd if=/dev/hda of=/dev/null bs=512 count=1 skip=$i > let i+=1 > done
35495734
1 + 0 registros en
1 + 0 graba fuera
35495735
dd: lectura de `/ dev / hda ‘: error de entrada / salida
0 + 0 registros en
0 + 0 graba fuera
35495751
dd: lectura de `/ dev / hda ‘: error de entrada / salida
0 + 0 registros en
0 + 0 graba fuera
35495752
1 + 0 registros en
1 + 0 graba fuera
Esto muestra que 17 sectores 35495735-35495751 son ilegibles.
Los bloques del sistema de archivos que contienen esta área son:
L = 35495735 hasta 35495751
S = 5269320
B = 4096
entonces b = 3778301 a 3778303
Para identificar archivos en estas ubicaciones, ejecutamos debugfs:
[root]# debugfs debugfs 1.32 (09-Nov-2002) debugfs: open /dev/hda3 debugfs: icheck 3778301 Block Inode number 3778301 45192 debugfs: icheck 3778302 Block Inode number 3778302 45192 debugfs: icheck 3778303 Block Inode number 3778303 45192 debugfs: ncheck 45192 Inode Pathname 45192 /S1/R/H/714979488-714985279/H-R-714979984-16.gwf debugfs: quit
Podemos usar md5sum para confirmar nuestro archivo:
[root]# md5sum /data/S1/R/H/714979488-714985279/H-R-714979984-16.gwf md5sum: /data/S1/R/H/714979488-714985279/H-R-714979984-16.gwf: Input/output error
Entonces, forzamos al disco a reasignar los bloques defectuosos:
[root]# dd if=/dev/zero of=/dev/hda3 bs=4096 count=3 seek=3778301 [root]# sync
o
[root]# dd if=/dev/zero of=/dev/hda bs=512 count=17 seek=35495735 [root]# sync
Ahora podemos comprobar si el bloque defectuoso no está creando problemas con el valor del atributo «Current_Pending_Sector» (comando smartctl -A):
ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE 5 Reallocated_Sector_Ct 0x0033 100 100 005 Pre-fail Always - 0 196 Reallocated_Event_Count 0x0032 100 100 000 Old_age Always - 0 197 Current_Pending_Sector 0x0022 100 100 000 Old_age Always - 0 198 Offline_Uncorrectable 0x0008 100 100 000 Old_age Offline - 0
Sectores no asignados
En los ejemplos anteriores, no hemos considerado el caso en el que los bloques defectuosos no se asignan a ningún archivo. Esto quedará claro cuando ejecutemos el comando debugfs para encontrar el archivo correspondiente a un bloque en particular. Si este es el caso, primero podemos crear un archivo que sea lo suficientemente grande para llenar el sistema de archivos restante (nuevamente, el comando dd es el rescate).
dd if=/dev/zero of=/some/mount/point bs=4k
Este comando se ejecutará hasta que no quede espacio en el sistema de archivos. Y ahora podemos continuar con el resto de los pasos.
BadBlock en ReiserFS
En este ejemplo, el sistema de archivos utilizado es ReiserFS. Entonces, algunos de los comandos utilizados serán diferentes del caso anterior.
El registro de errores SMART indica que la dirección del bloque defectuoso es 58656333. La tabla de particiones indica que el bloque está en una partición con el sistema de archivos ReiserFS, comenzando en la dirección del bloque 54781650.
Obtener el tamaño de bloque del sistema de archivos
# debugreiserfs /dev/hda3 | grep '^Blocksize' Blocksize: 4096
Obtener el número de bloque
# echo "(58656333-54781650)*512/4096" | bc -l 484335.37500000000000000000
Más información sobre el bloque
# debugreiserfs -1 484335 /dev/hda3 debugreiserfs 3.6.19 (2003 http://www.namesys.com) 484335 is free in ondisk bitmap
El problema ha ocurrido parece un problema de hardware.
Aquí vemos que la lectura del bloque falla. Pero ahora sabemos por esta salida que es un bloque sin usar.
En este punto, podemos intentar escribir el bloque defectuoso y ver si la unidad reasigna el bloque defectuoso. Si no puede reasignar el bloque, use la opción badblock (-B) con reiserfs utils para manejar este bloque correctamente.
bread: No se puede leer el bloque (484335): (Error de entrada / salida).
Abortado
Al menos tenemos el bloque defectuoso correcto.
Encuentra el archivo afectado
tar -cO /mydir | cat >/dev/null
Ejecute badblock -n para provocar la reasignación
# badblocks -b 4096 -p 3 -s -v -n /dev/hda3 `expr 484335 + 100` `expr 484335 - 100`
Si todo sucede como se esperaba, debugreiserfs -1 484335 / dev / hda3 no informa de errores. De lo contrario:
Use el comando dd para escribir ceros en el área en particular
# dd if=/dev/zero of=/dev/hda3 count=1 bs=4096 seek=484335 1+0 records in 1+0 records out 4096 bytes transferred in 0.007770 seconds (527153 bytes/sec)
LVM de reparación de Badblock
Este ejemplo considera que el badblock está en un volumen LVM:
Se informa un error y se encuentra que el bloque defectuoso está en LBA 37383668 con el siguiente comando:
# smartctl -a /dev/hdb ... SMART Self-test log structure revision number 1 Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error # 1 Short offline Completed: read failure 90% 66 37383668
sfdisk puede ayudar a encontrar la partición física del bloque defectuoso:
# sfdisk -luS /dev/hdb
O
# fdisk -ul /dev/hdb
Disk /dev/hdb: 9729 cylinders, 255 heads, 63 sectors/track Units = sectors of 512 bytes, counting from 0 Device Boot Start End #sectors Id System /dev/hdb1 63 996029 995967 82 Linux swap / Solaris /dev/hdb2 * 996030 1188809 192780 83 Linux /dev/hdb3 1188810 156296384 155107575 8e Linux LVM /dev/hdb4 0 - 0 0 Empty
El bloque defectuoso está en la partición / dev / hdb3, que es una partición basada en LVM. El desplazamiento de este bloque es: (37383668 – 1188810) = 36194858
La partición física utilizada por LVM se divide en PE (Extensión física). El comando ‘pvdisplay’ da el tamaño de PE de la partición LVM:
# part = / dev / hdb3; pvdisplay -c $ part | awk -F: ‘{imprimir $ 8}’
4096
Para obtener su tamaño en tamaño de bloque LBA (512 bytes o 0,5 KB), multiplicamos este número por 2: 4096 * 2 = 8192 bloques para cada PE.
Ahora buscamos el PE en el que reside el bloque defectuoso: número de bloque defectuoso de la partición física / tamaño de (PE)
36194858/8192 = 4418.3176
Ahora necesitamos encontrar la partición lógica correspondiente al número PE 4418.
# lvdisplay --maps |egrep 'Physical|LV Name|Type' LV Name /dev/WDC80Go/racine Type linear Physical volume /dev/hdb3 Physical extents 0 to 127 LV Name /dev/WDC80Go/usr Type linear Physical volume /dev/hdb3 Physical extents 128 to 1407 LV Name /dev/WDC80Go/var Type linear Physical volume /dev/hdb3 Physical extents 1408 to 1663 LV Name /dev/WDC80Go/tmp Type linear Physical volume /dev/hdb3 Physical extents 1664 to 1791 LV Name /dev/WDC80Go/home Type linear Physical volume /dev/hdb3 Physical extents 1792 to 3071 LV Name /dev/WDC80Go/ext1 Type linear Physical volume /dev/hdb3 Physical extents 3072 to 10751 LV Name /dev/WDC80Go/ext2 Type linear Physical volume /dev/hdb3 Physical extents 10752 to 18932
Por lo tanto, el PE 4418 está en la partición lógica / dev / WDC80Go / ext1.
El tamaño del bloque lógico del sistema de archivos en / dev / WDC80Go / ext1 es
# dumpe2fs /dev/WDC80Go/ext1 | grep 'Block size' dumpe2fs 1.37 (21-Mar-2005) Block size: 4096
La partición lógica comienza en PE 3072:
(# Inicio de partición de PE * tamaño de (PE)) + desplazamiento de partición[pe_start] = (3072 * 8192) + 384 = 25166208
Hay 512 bloques de partición física, por lo que el número de bloque defectuoso es:
(36194858 – 25166208) / (tamaño de (bloque fs) / 512) = 11028650 / (4096/512) = 1378581.25
Puede verificar si este es el bloque defectuoso real con el comando dd:
dd if=/dev/WDC80Go/ext1 of=block1378581 bs=4096 count=1 skip=1378581
Si el comando emite algún error, entonces el cálculo del bloque defectuoso es correcto. De lo contrario, vuelva a verificar los cálculos para encontrar el bloque correcto. Una vez que haya encontrado el bloque correcto, resuelva el problema con el comando dd como se explica en todos los ejemplos anteriores:
dd if=/dev/zero of=/dev/WDC80Go/ext1 count=1 bs=4096 seek=1378581
Conclusión
Todos los ejemplos dados en este artículo se concentran en encontrar el bloque defectuoso correcto y la partición. Una vez que haya encontrado el bloque defectuoso, todo lo que necesita hacer es ejecutar el comando dd para escribir ceros en el bloque. Los diferentes ejemplos proporcionan los métodos para encontrar la ubicación del bloque defectuoso en diferentes sistemas de archivos y en diferentes escenarios.