Linux - Reparando blocos defeituosos em uma matriz RAID1 com GPT

20

O tl; dr: como eu iria corrigir um bloco defeituoso em um disco em uma matriz RAID1?

Mas leia tudo sobre o que eu já tentei e possíveis erros nos meus métodos. Tentei ser o mais detalhado possível e estou realmente esperando por algum feedback

Esta é a minha situação: tenho dois discos de 2 TB (mesmo modelo) configurados em uma matriz RAID1 gerenciada por mdadm. Há cerca de 6 meses, notei o primeiro bloqueio ruim quando a SMART o denunciou. Hoje eu notei mais e agora estou tentando corrigi-lo.

Esta página do HOWTO parece ser o único artigo para o qual todos vinculam para corrigir os bloqueios reportados pela SMART. É uma página ótima, cheia de informações, porém está desatualizada e não aborda minha configuração específica. Aqui está como minha configuração é diferente:

  • Em vez de um disco, estou usando dois discos em uma matriz RAID1. Um disco está relatando erros enquanto o outro está bom. O HOWTO foi escrito com apenas um disco em mente, o que traz várias perguntas, como 'eu uso esse comando no dispositivo de disco ou no dispositivo RAID'?
  • Estou usando o GPT, que o fdisk não suporta. Eu tenho usado o gdisk e espero que ele esteja me fornecendo as mesmas informações que eu preciso

Então, vamos ao que interessa. Isto é o que eu fiz, no entanto, não parece estar funcionando. Sinta-se à vontade para verificar novamente meus cálculos e método quanto a erros. Os erros de relatório de disco são / 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

Com isso, concluímos que o erro reside no LBA 3212761936. Seguindo o HOWTO, eu uso o gdisk para encontrar o setor inicial a ser usado posteriormente na determinação do número do bloco (como não posso usar o fdisk, pois ele não suporta 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 tunefsacho que o tamanho do bloco é 4096. Usando essas informações e o cálculo do HOWTO, concluo que o bloco em questão é ((3212761936 - 2048) * 512) / 4096 = 401594986.

O HOWTO me instrui debugfsa ver se o bloco está em uso (eu uso o dispositivo RAID, pois ele precisa de um sistema de arquivos EXT, esse foi um dos comandos que me confundiu, pois eu não sabia, a princípio, se deveria usar / dev / sda ou / dev / md0):

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

Portanto, o bloco 401594986 é um espaço vazio, devo poder escrevê-lo sem problemas. Antes de escrever, porém, tento garantir que, de fato, não possa ser lido:

# 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

Se o bloco não pudesse ser lido, eu não esperaria que isso funcionasse. No entanto, ele faz. Repito usando /dev/sda, /dev/sda1, /dev/sdb, /dev/sdb1, /dev/md0, e + -5 ao número de bloco de pesquisa ao redor do bloco ruim. Tudo funciona. Dou de ombros e vou em frente e confirmo a gravação e a sincronização (eu uso / dev / md0 porque achei que modificar um disco e não o outro poderia causar problemas, dessa maneira os dois discos substituem o bloco defeituoso):

# 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 

Eu esperaria que a gravação no bloco defeituoso fizesse com que os discos reatribuíssem o bloco a um bom, no entanto, a execução de outro teste SMART mostra diferentemente:

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

Voltar à estaca 1. Então, basicamente, como eu consertaria um bloco defeituoso em 1 disco em uma matriz RAID1? Tenho certeza de que não fiz algo corretamente ...

Obrigado pelo seu tempo e paciência.


EDIT 1:

Eu tentei executar um longo teste SMART, com o mesmo LBA retornando como ruim (a única diferença é que ele reporta 30% restante em vez de 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

Eu também usei badblocks com a seguinte saída. A saída é estranha e parece estar com o formato errado, mas tentei testar os números emitidos como blocos, mas o debugfs fornece um erro

# 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

Não tenho certeza para onde ir a partir daqui. badblocksdefinitivamente encontrei algo, mas não sei o que fazer com as informações apresentadas ...


EDIT 2

Mais comandos e informações.

Eu me sinto como um idiota esquecendo de incluir isso originalmente. Esses são os valores SMART para /dev/sda. Eu tenho 1 Current_Pending_Sector e 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

De acordo com uma das respostas: parece que eu fiz interruptor seeke skippara dd. Eu estava usando a busca, pois é isso que é usado com o HOWTO. O uso deste comando faz ddcom que seja travado: # dd if = / dev / sda1 de = / dev / null bs = 4096 count = 1 skip = 401594986

O uso de blocos em torno desse (..84, ..85, ..87, ..88) parece funcionar muito bem, e o uso de / dev / sdb1 com 401594986leituras de bloco também é bom (como esperado, quando o disco passou no teste SMART) ) Agora, a pergunta que tenho é: Ao escrever sobre esta área para reatribuir os blocos, uso /dev/sda1ou /dev/md0? Não quero causar problemas com a matriz RAID gravando diretamente em um disco e não tendo a outra atualização de disco.

EDIT 3

A gravação no bloco produziu diretamente erros no sistema de arquivos. Eu escolhi uma resposta que resolveu o problema rapidamente:

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

Obrigado a todos que ajudaram. =)

Blitzmann
fonte
Você conseguiu ler o bloco, para que não seja danificado. Portanto, não há setores realocados. Eu verifiquei o cálculo do seu bloco fs e parece legítimo. Quando fiz realocações ruins de blocos, descobri que às vezes o teste curto inteligente não relatava o bloco incorreto corretamente. Enquanto isso, você pode executar o longo teste offline smartctl -t long /dev/sdae ver se o LBA do primeiro erro é alterado.
Jari Laamanen
11
Tente /sbin/badblocks -sv /dev/sdaverificar o disco.
perfil completo de jippie
Fiz as duas sugestões e atualizei a postagem de acordo. Ainda preso. = /
blitzmann
O smartctl relata uma contagem de Current_Pending_Sector diferente de zero? Offline_Uncorrectable é diferente de zero?
mgorven
Por favor, adicione o status da matriz à pergunta:sudo mdadm -D /dev/md0
psusi

Respostas:

20

Todas essas respostas "cutucam o setor" são, francamente, insanas. Eles arriscam (possivelmente ocultos) a corrupção do sistema de arquivos. Se os dados já tivessem sumido, porque esse disco armazenava a única cópia, seria razoável. Mas há uma cópia perfeitamente boa no espelho.

Você só precisa ter medo de esfregar o espelho. Ele notará o setor defeituoso e o reescreverá automaticamente.

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

Você precisa colocar o dispositivo certo (por exemplo, md0 em vez de mdX). Isso levará um tempo, como ocorre com toda a matriz por padrão. Em um kernel novo o suficiente, você pode escrever os números do setor para sync_min / sync_max primeiro, para limitá-lo a apenas uma parte da matriz.

Esta é uma operação segura. Você pode fazer isso em todos os seus dispositivos mdraid. Na verdade, você deve fazê-lo em todos os seus dispositivos mdraid, regularmente. Sua distribuição provavelmente é fornecida com um cronjob para lidar com isso, talvez você precise fazer algo para ativá-la?


Script para todos os dispositivos RAID no sistema

Há um tempo atrás, escrevi esse script para "reparar" todos os dispositivos RAID no sistema. Isso foi escrito para versões mais antigas do kernel, nas quais apenas 'reparo' corrigia o setor defeituoso; agora apenas a verificação é suficiente (o reparo ainda funciona bem nos kernels mais recentes, mas também re-copia / reconstrói a paridade, o que nem sempre é o que você deseja, especialmente em 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

Se você deseja fazer em checkvez de repair, então este primeiro bloco (não testado) deve 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
derobert
fonte
Obrigado por isso. Recentemente, voltei a esse problema, esperando finalmente resolvê-lo. Eu escrevi no bloco / dev / md0 e tive problemas no sistema de arquivos, mas felizmente, depois de algumas horas de terror e inicializando em shells de recuperação, tudo foi reparado sem nenhum dataloss. Tentarei o seu método primeiro e espero que isso me livre do setor pendente. =)
blitzmann
Como você pode saber quando a limpeza está concluída? Vai cat /sys/block/mdX/md/sync_actionler 'ocioso' quando terminar?
11134 Jon Cram
@JonCram sim, e você pode assistir o status por cat /proc/mdstatou se você está querendo roteiro lo,/sys/…/sync_completed
derobert
5

Acabei de ter praticamente o mesmo problema com uma matriz RAID1. O setor defeituoso estava logo no início de uma das partições - setor 16 de / dev / sdb2. Eu segui as instruções acima: depois de verificar se o bloco lógico 2 não estava sendo usado pelo sistema de arquivos e tomando cuidado para obter o dd seek e pular o caminho certo, e zeramos o bloco do sistema de zeros 1:

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

O que isso fez? Não consertou o setor ruim. Agora, eu sei, é porque / dev / md0 não é mapeado diretamente para / dev / sdb2, você precisa levar em consideração o RAID DATA OFFSET! Mais sobre isso abaixo. O que ele fez foi um pouco, mas potencialmente devastador, do meu sistema de arquivos. Acontece que o bloco lógico 2 de / dev / md0 continha metadados úteis do sistema de arquivos e funcionava bem em ambos os discos, até que eu tenha cagado nas duas cópias escrevendo em / dev / md0. Felizmente, o e2fsck -y / dev / md0 resolveu o problema (depois de exibir uma quantidade alarmante de saída) sem perda aparente de dados. Lição aprendida: se o debugfs icheck diz 'bloco não encontrado', isso não significa necessariamente que os setores correspondentes não são usados.

De volta ao deslocamento de dados: use mdadm para encontrar o deslocamento assim:

# 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)

Nesse caso, o deslocamento de dados é 262144 setores de 512 bytes. Se você dd de / dev / md0 e compará-lo com os dados da partição bruta com um deslocamento de 131072K, verá que eles correspondem. Portanto, no meu caso, o bloco lógico 2 (setores 16 a 23) de / dev / sdb2 nem mesmo está no sistema de arquivos; eles estão no superbloco RAID, sobre o qual você pode ler aqui: https://raid.wiki.kernel.org/index.php/RAID_superblock_formats - para a versão 1.2, consiste em 256 bytes + 2 bytes por dispositivo na matriz , todos iniciando 4096 bytes em, portanto, no meu caso, o setor inválido não foi usado. Os setores correspondentes de / dev / sdc2 (a outra metade da matriz RAID1) são zero, então imaginei que seria seguro fazer isso:

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

Funcionou!

Samer
fonte
OP aqui. Obrigado por esta informação. Quando esse problema surgiu, dei o salto e zerou o bloco no nível / dev / md0. Má ideia, como aconteceu com o meu sistema de arquivos também. Felizmente, depois de um período de tempo indecoroso em reparos, tudo parecia bem, sem problemas. Mas com o pânico inicial eu esqueci completamente deste post. Recentemente, configurei meu servidor no meu novo apartamento, e essa é uma das coisas da minha lista de tarefas mais uma vez, e agradeço a sua compreensão do problema. Vou atualizar o OP quando eu começar a cavar isso um pouco mais. =)
blitzmann
2

Se estiver executando o debian, você provavelmente terá um trabalho no /etc/cron.d/mdadm. Isso ocorrerá no /usr/share/mdadm/checkarray --cron --all --idle --quiet primeiro domingo de cada mês. Execute isso manualmente quando você receber erros de hardware incorrigíveis para acelerar a reescrita.

Håkon Alstadheim
fonte
Bem, ao executá-lo manualmente, você provavelmente deseja sair --cron.
Derobert 13/08/16
1

Você confundiu seus ddargumentos. seekfaz com que ele busque o deslocamento especificado na saída . Você queria skipbloquear a entrada .

psusi
fonte
Obrigado! Atualizei a postagem original para incluir dados desta. Se você puder me dizer como consertar o bloqueio a partir daqui, acho que lhe concedo resposta. (Eu sou incerto se eu deveria escrever diretamente para /dev/sda1/ou o uso /dev/md0de bloco de substituição) =)
blitzmann
@ Ryan, escrever para md0 deve ser o caminho a seguir, embora sda1 também deva funcionar.
Psusi 06/07/12
0

Se você tiver um sw-raid1 e gravar dados diretamente em um dos membros, terá um ataque corrompido imediatamente. NÃO grave dados em um sdaX ou sdbX se eles fizerem parte de um mdX. Se você gravar no mdX, os dados serão copiados para as duas unidades; se você ler no mdX, os dados serão lidos em uma das unidades.

Jose Tavares
fonte