Linux: reparación de bloques defectuosos en una matriz RAID1 con GPT


20

El tl; dr: ¿cómo haría para arreglar un bloque defectuoso en 1 disco en una matriz RAID1?

Pero lea todo esto por lo que ya he probado y posibles errores en mis métodos. He tratado de ser lo más detallado posible, y realmente espero algún comentario

Esta es mi situación: tengo dos discos de 2TB (mismo modelo) configurados en una matriz RAID1 administrada por mdadm. Hace unos 6 meses, noté el primer bloqueo incorrecto cuando SMART lo informó. Hoy noté más, y ahora estoy tratando de arreglarlo.

Esta página de CÓMO parece ser el único artículo al que todos se vinculan para reparar los bloques defectuosos que SMART informa. Es una gran página, llena de información, sin embargo, está bastante desactualizada y no aborda mi configuración particular. Así es como mi configuración es diferente:

  • En lugar de un disco, estoy usando dos discos en una matriz RAID1. Un disco informa errores mientras que el otro está bien. El CÓMO está escrito con un solo disco en mente, lo que plantea varias preguntas como '¿uso este comando en el dispositivo de disco o en el dispositivo RAID'?
  • Estoy usando GPT, que fdisk no es compatible. He estado usando gdisk en su lugar, y espero que me esté dando la misma información que necesito

Entonces, pongámonos manos a la obra. Esto es lo que he hecho, sin embargo, no parece estar funcionando. Por favor, siéntase libre de verificar mis cálculos y método para detectar errores. El disco que informa errores es / dev / sda:

# smartctl -l selftest /dev/sda
smartctl 5.42 2011-10-20 r3458 [x86_64-linux-3.4.4-2-ARCH] (local build)
Copyright (C) 2002-11 by Bruce Allen, http://smartmontools.sourceforge.net

=== START OF READ SMART DATA SECTION ===
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%     12169         3212761936

Con esto, deducimos que el error reside en LBA 3212761936. Siguiendo el CÓMO, uso gdisk para encontrar el sector de inicio que se usará más adelante para determinar el número de bloque (ya que no puedo usar fdisk ya que no es compatible con GPT):

# gdisk -l /dev/sda
GPT fdisk (gdisk) version 0.8.5

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with protective MBR; using GPT.
Disk /dev/sda: 3907029168 sectors, 1.8 TiB
Logical sector size: 512 bytes
Disk identifier (GUID): CFB87C67-1993-4517-8301-76E16BBEA901
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 3907029134
Partitions will be aligned on 2048-sector boundaries
Total free space is 2014 sectors (1007.0 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048      3907029134   1.8 TiB     FD00  Linux RAID

Usando tunefsencuentro el blockize ser 4096. Usando esta información y el cálculo del CÓMO, concluyo que el bloque en cuestión es ((3212761936 - 2048) * 512) / 4096 = 401594986.

Luego, el CÓMO me dirige debugfsa ver si el bloque está en uso (uso el dispositivo RAID ya que necesita un sistema de archivos EXT, este fue uno de los comandos que me confundió, ya que al principio no sabía si debía usar / dev / sda o / dev / md0):

# debugfs
debugfs 1.42.4 (12-June-2012)
debugfs:  open /dev/md0
debugfs:  testb 401594986
Block 401594986 not in use

Entonces, el bloque 401594986 es un espacio vacío, debería poder escribir sobre él sin problemas. Sin embargo, antes de escribirle, trato de asegurarme de que, de hecho, no se pueda leer:

# dd if=/dev/sda1 of=/dev/null bs=4096 count=1 seek=401594986
1+0 records in
1+0 records out
4096 bytes (4.1 kB) copied, 0.000198887 s, 20.6 MB/s

Si el bloque no se pudiera leer, no esperaría que esto funcione. Sin embargo, lo hace. Repito usando /dev/sda, /dev/sda1, /dev/sdb, /dev/sdb1, /dev/md0, y + -5 al número de bloque para buscar en todo el bloque defectuoso. Todo funciona Me encojo de hombros y sigo escribiendo y sincronizando (uso / dev / md0 porque pensé que modificar un disco y no el otro podría causar problemas, de esta manera ambos discos sobrescriben el bloque defectuoso):

# dd if=/dev/zero of=/dev/md0 bs=4096 count=1 seek=401594986
1+0 records in
1+0 records out
4096 bytes (4.1 kB) copied, 0.000142366 s, 28.8 MB/s
# sync 

Esperaría que escribir en el bloque incorrecto haga que los discos reasignen el bloque a uno bueno, sin embargo, ejecutar otra prueba SMART muestra de manera diferente:

# 1  Short offline       Completed: read failure       90%     12170         3212761936

De vuelta al cuadro 1. Entonces, ¿cómo solucionaría un bloque defectuoso en 1 disco en una matriz RAID1? Estoy seguro de que no he hecho algo correctamente ...

Gracias por su tiempo y paciencia.


EDITAR 1:

Intenté ejecutar una prueba SMART larga, con el mismo LBA regresando como malo (la única diferencia es que informa que queda un 30% en lugar del 90%):

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       30%     12180         3212761936
# 2  Short offline       Completed: read failure       90%     12170         3212761936

También he usado badblocks con el siguiente resultado. El resultado es extraño y parece tener un formato incorrecto, pero intenté probar los números que salen como bloques, pero debugfs da un error

# badblocks -sv /dev/sda
Checking blocks 0 to 1953514583
Checking for bad blocks (read-only test): 1606380968ne, 3:57:08 elapsed. (0/0/0 errors)
1606380969ne, 3:57:39 elapsed. (1/0/0 errors)
1606380970ne, 3:58:11 elapsed. (2/0/0 errors)
1606380971ne, 3:58:43 elapsed. (3/0/0 errors)
done
Pass completed, 4 bad blocks found. (4/0/0 errors)
# debugfs
debugfs 1.42.4 (12-June-2012)
debugfs:  open /dev/md0
debugfs:  testb 1606380968
Illegal block number passed to ext2fs_test_block_bitmap #1606380968 for block bitmap for /dev/md0
Block 1606380968 not in use

No estoy seguro de a dónde ir desde aquí. badblocksDefinitivamente encontré algo, pero no estoy seguro de qué hacer con la información presentada ...


EDITAR 2

Más comandos e información.

Me siento como un idiota olvidando incluir esto originalmente. Estos son valores SMART para /dev/sda. Tengo 1 Current_Pending_Sector y 0 Offline_Uncorrectable.

SMART Attributes Data Structure revision number: 16
Vendor Specific SMART Attributes with Thresholds:
ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE
  1 Raw_Read_Error_Rate     0x002f   100   100   051    Pre-fail  Always       -       166
  2 Throughput_Performance  0x0026   055   055   000    Old_age   Always       -       18345
  3 Spin_Up_Time            0x0023   084   068   025    Pre-fail  Always       -       5078
  4 Start_Stop_Count        0x0032   100   100   000    Old_age   Always       -       75
  5 Reallocated_Sector_Ct   0x0033   252   252   010    Pre-fail  Always       -       0
  7 Seek_Error_Rate         0x002e   252   252   051    Old_age   Always       -       0
  8 Seek_Time_Performance   0x0024   252   252   015    Old_age   Offline      -       0
  9 Power_On_Hours          0x0032   100   100   000    Old_age   Always       -       12224
 10 Spin_Retry_Count        0x0032   252   252   051    Old_age   Always       -       0
 11 Calibration_Retry_Count 0x0032   252   252   000    Old_age   Always       -       0
 12 Power_Cycle_Count       0x0032   100   100   000    Old_age   Always       -       75
181 Program_Fail_Cnt_Total  0x0022   100   100   000    Old_age   Always       -       1646911
191 G-Sense_Error_Rate      0x0022   100   100   000    Old_age   Always       -       12
192 Power-Off_Retract_Count 0x0022   252   252   000    Old_age   Always       -       0
194 Temperature_Celsius     0x0002   064   059   000    Old_age   Always       -       36 (Min/Max 22/41)
195 Hardware_ECC_Recovered  0x003a   100   100   000    Old_age   Always       -       0
196 Reallocated_Event_Count 0x0032   252   252   000    Old_age   Always       -       0
197 Current_Pending_Sector  0x0032   100   100   000    Old_age   Always       -       1
198 Offline_Uncorrectable   0x0030   252   100   000    Old_age   Offline      -       0
199 UDMA_CRC_Error_Count    0x0036   200   200   000    Old_age   Always       -       0
200 Multi_Zone_Error_Rate   0x002a   100   100   000    Old_age   Always       -       30
223 Load_Retry_Count        0x0032   252   252   000    Old_age   Always       -       0
225 Load_Cycle_Count        0x0032   100   100   000    Old_age   Always       -       77

# mdadm -D /dev/md0
/dev/md0:
        Version : 1.2
  Creation Time : Thu May  5 06:30:21 2011
     Raid Level : raid1
     Array Size : 1953512383 (1863.01 GiB 2000.40 GB)
  Used Dev Size : 1953512383 (1863.01 GiB 2000.40 GB)
   Raid Devices : 2
  Total Devices : 2
    Persistence : Superblock is persistent

    Update Time : Tue Jul  3 22:15:51 2012
          State : clean
 Active Devices : 2
Working Devices : 2
 Failed Devices : 0
  Spare Devices : 0

           Name : server:0  (local to host server)
           UUID : e7ebaefd:e05c9d6e:3b558391:9b131afb
         Events : 67889

    Number   Major   Minor   RaidDevice State
       2       8        1        0      active sync   /dev/sda1
       1       8       17        1      active sync   /dev/sdb1

Según una de las respuestas: parece que cambié seeky skippara dd. Estaba usando la búsqueda ya que eso es lo que se usa con el CÓMO. El uso de este comando hace ddque se cuelgue: # dd if = / dev / sda1 of = / dev / null bs = 4096 count = 1 skip = 401594986

El uso de bloques alrededor de ese (..84, ..85, ..87, ..88) parece funcionar bien, y el uso de / dev / sdb1 con 401594986lecturas de bloque también está bien (como se esperaba, ya que ese disco pasó la prueba SMART ) Ahora, la pregunta que tengo es: al escribir sobre esta área para reasignar los bloques, ¿uso /dev/sda1o /dev/md0? No quiero causar ningún problema con la matriz RAID al escribir directamente en un disco y no tener la otra actualización de disco.

EDITAR 3

Escribir en el bloque produjo directamente errores en el sistema de archivos. Elegí una respuesta que resolvió el problema rápidamente:

# 1  Short offline       Completed without error       00%     14211         -
# 2  Extended offline    Completed: read failure       30%     12244         3212761936

Gracias a todos los que ayudaron. =)


Pudiste leer el bloque, por lo que no está dañado. Por lo tanto, no hay sectores reasignados. Revisé tu cálculo de bloque fs y parece legítimo. Cuando hice reasignaciones de bloque malas, descubrí que a veces la prueba corta inteligente no informaba el bloqueo ofensivo correctamente. Mientras tanto, puede ejecutar la prueba sin conexión larga smartctl -t long /dev/sday ver si cambia el LBA del primer error.
Jari Laamanen

1
Intenta /sbin/badblocks -sv /dev/sdarevisar el disco.
jippie

He hecho ambas sugerencias y he actualizado la publicación en consecuencia. Aún atorado. = /
blitzmann

¿Smartctl informa un recuento actual_de_ejecución_de_ejemplo distinto de cero? ¿Offline_Uncorrectable no es cero?
mgorven

Agregue el estado de la matriz a la pregunta:sudo mdadm -D /dev/md0
psusi

Respuestas:


20

Todas estas respuestas de "meter el sector" son, francamente, una locura. Corren el riesgo (posiblemente oculto) de corrupción del sistema de archivos. Si los datos ya se hubieran ido, porque ese disco almacenaba la única copia, sería razonable. Pero hay una copia perfectamente buena en el espejo.

Solo necesita que mdraid friegue el espejo. Notará el sector defectuoso y lo reescribirá automáticamente.

# echo 'check' > /sys/block/mdX/md/sync_action    # use 'repair' instead for older kernels

Debe colocar el dispositivo correcto allí (por ejemplo, md0 en lugar de mdX). Esto llevará un tiempo, como lo hace toda la matriz de forma predeterminada. En un kernel lo suficientemente nuevo, primero puede escribir números de sector en sync_min / sync_max, para limitarlo a solo una parte de la matriz.

Esta es una operación segura. Puede hacerlo en todos sus dispositivos mdraid. De hecho, debe hacerlo en todos sus dispositivos mdraid, regularmente. Es probable que su distribución se envíe con un cronjob para manejar esto, ¿tal vez necesite hacer algo para habilitarlo?


Script para todos los dispositivos RAID en el sistema

Hace un tiempo, escribí este script para "reparar" todos los dispositivos RAID en el sistema. Esto fue escrito para versiones anteriores del kernel donde solo 'reparar' arreglaría el sector defectuoso; ahora solo hacer la comprobación es suficiente (la reparación aún funciona bien en los núcleos más nuevos, pero también vuelve a copiar / reconstruir la paridad, que no siempre es lo que desea, especialmente en unidades flash)

#!/bin/bash

save="$(tput sc)";
clear="$(tput rc)$(tput el)";
for sync in /sys/block/md*/md/sync_action; do
    md="$(echo "$sync" | cut -d/ -f4)"
    cmpl="/sys/block/$md/md/sync_completed"

    # check current state and get it repairing.
    read current < "$sync"
    case "$current" in
        idle)
            echo 'repair' > "$sync"
            true
            ;;
        repair)
            echo "WARNING: $md already repairing"
            ;;
        check)
            echo "WARNING: $md checking, aborting check and starting repair"
            echo 'idle' > "$sync"
            echo 'repair' > "$sync"
            ;;
        *)
            echo "ERROR: $md in unknown state $current. ABORT."
            exit 1
            ;;
    esac

    echo -n "Repair $md...$save" >&2
    read current < "$sync"
    while [ "$current" != "idle" ]; do
        read stat < "$cmpl"
        echo -n "$clear $stat" >&2
        sleep 1
        read current < "$sync"
    done
    echo "$clear done." >&2;
done

for dev in /dev/sd?; do
    echo "Starting offline data collection for $dev."
    smartctl -t offline "$dev"
done

Si desea hacer en checklugar de repair, entonces este primer bloque (no probado) debería funcionar:

    case "$current" in
        idle)
            echo 'check' > "$sync"
            true
            ;;
        repair|check)
            echo "NOTE: $md $current already in progress."
            ;;
        *)
            echo "ERROR: $md in unknown state $current. ABORT."
            exit 1
            ;;
    esac

Gracias por esto. Recientemente volví a este problema con la esperanza de finalmente resolverlo. Escribí en el bloque / dev / md0 y tuve problemas con el sistema de archivos, pero afortunadamente después de algunas horas de terror y arrancando en los shells de recuperación, todo fue reparaciones sin daños. Probaré su método primero y espero que esto me libere del sector pendiente. =)
blitzmann

¿Cómo puede saber cuándo se completa el exfoliante? ¿ cat /sys/block/mdX/md/sync_actionLeerá 'inactivo' cuando haya terminado?
Jon Cram

@ JonCram sí, y puedes ver el estado por cat /proc/mdstato si quieres escribirlo,/sys/…/sync_completed
derobert

5

Acabo de tener casi el mismo problema con una matriz RAID1. El sector defectuoso estaba justo al comienzo de una de las particiones: el sector 16 de / dev / sdb2. Seguí las instrucciones anteriores: después de verificar que el bloque de sistema lógico 2 no estaba en uso por el sistema de archivos y de tener cuidado de conseguir dd seek y skip de la manera correcta, y cerré a cero 1 bloque del sistema de archivos:

# dd if=/dev/zero of=/dev/md0 bs=4096 count=1 seek=2

¿Qué hizo esto? No solucionó el mal sector. Esto, ahora lo sé, es porque / dev / md0 no se asigna directamente a / dev / sdb2, ¡debe tener en cuenta la DESPLAZAMIENTO DE DATOS RAID! Más sobre esto a continuación. Lo que hizo fue una pequeña pero potencialmente devastadora turd en mi sistema de archivos. Resulta que el bloque lógico 2 de / dev / md0 contenía metadatos útiles del sistema de archivos y estaba bien en ambos discos, hasta que me quedé en ambas copias escribiendo en / dev / md0. Afortunadamente, e2fsck -y / dev / md0 solucionó el problema (después de arrojar una cantidad alarmante de salida) sin pérdida aparente de datos. Lección aprendida: si debugfs icheck dice 'bloque no encontrado', no significa necesariamente que no se usen los sectores correspondientes.

Volver al desplazamiento de datos: use mdadm para encontrar el desplazamiento de esta manera:

# mdadm --examine /dev/sdb2
/dev/sdb2:
          Magic : a92b4efc
        Version : 1.2
    Feature Map : 0x0
     Array UUID : ef7934b9:24696df9:b89ff03e:b4e5a05b
           Name : XXXXXXXX
  Creation Time : Sat Sep  1 01:20:22 2012
     Raid Level : raid1
   Raid Devices : 2

 Avail Dev Size : 1953241856 (931.38 GiB 1000.06 GB)
     Array Size : 976620736 (931.38 GiB 1000.06 GB)
  Used Dev Size : 1953241472 (931.38 GiB 1000.06 GB)
    Data Offset : 262144 sectors
   Super Offset : 8 sectors
          State : clean
    Device UUID : f3b5d515:446d4225:c2191fa0:9a9847b8

    Update Time : Thu Sep  6 12:11:24 2012
       Checksum : abb47d8b - correct
         Events : 54


    Device Role : Active device 0
    Array State : AA ('A' == active, '.' == missing)

En este caso, el desplazamiento de datos es 262144 sectores de 512 bytes. Si dd desde / dev / md0 y lo compara con los datos de la partición sin formato con un desplazamiento de 131072K, encontrará que coinciden. Entonces, en mi caso, el bloque lógico 2 (sectores 16-23) de / dev / sdb2 ni siquiera está en el sistema de archivos; están en el superbloque RAID, sobre el que puede leer aquí: https://raid.wiki.kernel.org/index.php/RAID_superblock_formats : para la versión 1.2, consta de 256 bytes + 2 bytes por dispositivo en la matriz , todos a partir de 4096 bytes, por lo que en mi caso, el sector defectuoso no se utilizó. Los sectores correspondientes de / dev / sdc2 (la otra mitad de la matriz RAID1) son cero, así que pensé que sería seguro hacer esto:

# dd if=/dev/zero of=/dev/sdb2 bs=4096 count=1 seek=2

¡Funcionó!


OP aquí. Gracias por esta información. Cuando surgió este problema para mí, di el salto y cerré el bloque en el nivel / dev / md0. Mala idea, ya que resultó que también arruinaba mi sistema de archivos. Afortunadamente, después de un tiempo impío de reparación, todo parecía estar bien sin daños. Pero con el pánico inicial, me olvidé por completo de esta publicación. Recientemente configuré mi servidor en mi nuevo apartamento, y esta es una de las cosas en mi lista de tareas una vez más, y le agradezco su comprensión del problema. Actualizaré el OP cuando llegue a investigar un poco más sobre esto. =)
blitzmann

2

Si ejecuta Debian, lo más probable es que tenga un trabajo en /etc/cron.d/mdadm. Esto se ejecutará el /usr/share/mdadm/checkarray --cron --all --idle --quiet primer domingo de cada mes. Ejecútelo manualmente cuando obtenga errores de hardware que no se pueden corregir para acelerar la reescritura.


Bueno, cuando lo ejecutas manualmente, probablemente quieras dejarlo --cron.
derobert

1

Confundiste tus ddargumentos. seekhace que busque el desplazamiento especificado en la salida . Querías skipbloquear en la entrada .


¡Gracias! He actualizado la publicación original para incluir datos de esto. Si pudieras decirme cómo arreglar el bloqueo desde aquí, creo que te concederé una respuesta. (No estoy seguro si debo escribir directamente /dev/sda1/o usar /dev/md0para sobrescribir el bloque) =)
blitzmann

@ Ryan, escribir en md0 debería ser el camino a seguir, aunque sda1 también debería funcionar.
psusi

0

Si tienes un sw-raid1 y escribes datos directamente a uno de los miembros, inmediatamente tendrás un ataque corrupto. NO escriba datos en un sdaX o sdbX si son parte de un mdX. Si escribe en mdX, tendrá los datos copiados en ambas unidades, si lee desde mdX, tendrá los datos leídos desde una de las unidades.

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.