LINUX

Cómo arreglar / reparar bloques defectuosos en Linux

Reparar bloques defectuosos de 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.

Publicaciones relacionadas

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Botón volver arriba
Cerrar