Falha no dispositivo em md RAID quando o ATA pára de responder

4

Eu criei cinco partições de HDD de 1TB ( /dev/sda1 , /dev/sdb1 , /dev/sdc1 , /dev/sde1 e /dev/sdf1 ) em um RAID 6 array chamado /dev/md0 using mdadm no Ubuntu 14.04 LTS Trusty Tahr.

O comando sudo mdadm --detail /dev/md0 usado para mostrar todas as unidades na sincronização ativa .

Então, para testar, eu simulei um longo bloqueio de E / S em /dev/sdb executando esses comandos enquanto /dev/sdb1 ainda estava ativo na matriz:

hdparm --user-master u --security-set-pass deltik /dev/sdb
hdparm --user-master u --security-erase-enhanced deltik /dev/sdb

WARNING

DON'T TRY THIS ON DATA YOU CARE ABOUT!
I ended up corrupting 455681 inodes as a result of this ATA operation. I admit my negligence.

O comando ATA para apagamento seguro deve ser executado por 188 minutos, bloqueando todos os outros comandos por pelo menos esse tempo.

Eu esperava que md deixasse a unidade sem resposta como um controlador RAID adequado, mas, para minha surpresa, /dev/md0 também foi bloqueado.

mdadm --detail /dev/md0 consulta o dispositivo bloqueado, por isso congela e não produz.

Aqui está o layout de /proc/mdstat , enquanto não consigo usar mdadm --detail /dev/md0 :

root@node51 [~]# cat /proc/mdstat 
Personalities : [raid6] [raid5] [raid4] [linear] [multipath] [raid0] [raid1] [raid10] 
md0 : active raid6 sdf1[5] sda1[0] sdb1[4] sdc1[2] sde1[1]
      2929887744 blocks super 1.2 level 6, 512k chunk, algorithm 2 [5/5] [UUUUU]

unused devices: <none>

Eu tentei mdadm /dev/md0 -f /dev/sdb1 falhar com força em /dev/sdb1 , mas isso também foi bloqueado:

root@node51 [~]# ps aux | awk '{if($8~"D"||$8=="STAT"){print $0}}' 
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root      3334  1.2  0.0  42564  1800 ?        D    03:21   3:37 parted -l
root      4957  0.0  0.0  13272   900 ?        D    06:19   0:00 mdadm /dev/md0 -f /dev/sdb1
root      5706  0.0  0.0  13388  1028 ?        D    06:19   0:00 mdadm --detail /dev/md0
root      7541  0.5  0.0      0     0 ?        D    Jul19   6:12 [kworker/u16:2]
root     22420  0.0  0.0  11480   808 ?        D    07:48   0:00 lsblk
root     22796  0.0  0.0   4424   360 pts/13   D+   05:51   0:00 hdparm --user-master u --security-erase-enhanced deltik /dev/sdb
root     23312  0.0  0.0   4292   360 ?        D    05:51   0:00 hdparm -I /dev/sdb
root     23594  0.1  0.0      0     0 ?        D    06:11   0:07 [kworker/u16:1]
root     25205  0.0  0.0  17980   556 ?        D    05:52   0:00 ls --color=auto
root     26008  0.0  0.0  13388  1032 pts/23   D+   06:32   0:00 mdadm --detail /dev/md0
dtkms    29271  0.0  0.2  58336 10412 ?        DN   05:55   0:00 python /usr/share/backintime/common/backintime.py --backup-job
root     32303  0.0  0.0      0     0 ?        D    06:16   0:00 [kworker/u16:0]

ATUALIZAÇÃO (21 de julho de 2015): Depois de aguardar os 188 minutos completos para que o bloqueio de I / O fosse limpo, a surpresa se transformou em horror quando vi que md tratou completamente /dev/sdb como se estivesse completamente intacto.

Eu achei que md teria, pelo menos, visto que a paridade era incompatível e, em seguida, teria perdido /dev/sdb1 .

Em pânico, corri mdadm /dev/md0 -f /dev/sdb1 novamente e, como o bloco de E / S foi removido, o comando foi concluído rapidamente.

A corrupção do sistema de arquivos já estava acontecendo conforme os erros de entrada / saída apareciam. Ainda em pânico, fiz uma desmontada preguiça da partição de dados na matriz RAID e um reboot -nf , já que achei que não poderia piorar.

Após um e2fsck na partição, os inodes 455681 transformaram em lost+found .

Eu já reagrupei o array, e o array em si parece bem agora:

root@node51 [~]# mdadm --detail /dev/md0
/dev/md0:
        Version : 1.2
  Creation Time : Mon Feb 16 14:34:26 2015
     Raid Level : raid6
     Array Size : 2929887744 (2794.16 GiB 3000.21 GB)
  Used Dev Size : 976629248 (931.39 GiB 1000.07 GB)
   Raid Devices : 5
  Total Devices : 5
    Persistence : Superblock is persistent

    Update Time : Tue Jul 21 00:00:30 2015
          State : active 
 Active Devices : 5
Working Devices : 5
 Failed Devices : 0
  Spare Devices : 0

         Layout : left-symmetric
     Chunk Size : 512K

           Name : box51:0
           UUID : 6b8a654d:59deede9:c66bd472:0ceffc61
         Events : 643541

    Number   Major   Minor   RaidDevice State
       0       8        1        0      active sync   /dev/sda1
       1       8       97        1      active sync   /dev/sdg1
       2       8       33        2      active sync   /dev/sdc1
       6       8       17        3      active sync   /dev/sdb1
       5       8      113        4      active sync   /dev/sdh1

Ainda é um choque para mim que md não tenha duas linhas de proteção que eu esperava:

  • Falha no dispositivo quando ele é bloqueado
  • Falha em um dispositivo quando os dados retornados são lixo

Perguntas

  1. Por que o md não falha na unidade / partição que não responde?
  2. Posso soltar a unidade / partição da matriz enquanto a unidade está bloqueada?
  3. O tempo limite pode ser configurado para que md automaticamente falhe em uma unidade que não esteja respondendo aos comandos ATA?
  4. Por que md continua usando um dispositivo com dados inválidos?
por Deltik 20.07.2015 / 15:21

1 resposta

2

Deltik , você entendeu mal como funciona o Linux Software RAID ( md ).

md cria um dispositivo de bloco virtual a partir de vários dispositivos ou partições e não sabe quais dados você está transferindo para e do dispositivo virtual.
Você esperava poder fazer coisas para as quais não foi projetado.

Respostas

1. Por que não md falha na unidade / partição sem resposta?

Isso ocorre porque md não faz ideia se

  • a unidade está ocupada com E / S de algo que md solicitou ou
  • a unidade foi bloqueada devido a alguma circunstância externa, como a recuperação de erros da própria unidade ou, no seu caso, uma ATA Secure Erase,

, então md esperará para ver o que a unidade retorna. A unidade eventualmente não retornou nenhum erro de leitura ou gravação. Se houvesse um erro de leitura, md teria automaticamente corrigido a paridade, e se houvesse um erro de gravação, md teria falhado o dispositivo (consulte a seção "Recuperação" do md man page ).

Como não houve erro de leitura nem erro de gravação, md continuou usando o dispositivo depois que o kernel aguardou a resposta.

2. Posso soltar a unidade / partição da matriz enquanto a unidade está bloqueada?

Não. O dispositivo /dev/md0 RAID está bloqueado e não pode ser modificado até que o bloco seja limpo.

Você passou o sinal -f ou --fail para o modo mdadm "Gerenciar".
Aqui está um passo a passo do que isso realmente faz:

Este é o código-fonte de como esse sinalizador funciona :

case 'f': /* set faulty */
    /* FIXME check current member */
    if ((sysfd >= 0 && write(sysfd, "faulty", 6) != 6) ||
        (sysfd < 0 && ioctl(fd, SET_DISK_FAULTY,
                rdev))) {
        if (errno == EBUSY)
            busy = 1;
        pr_err("set device faulty failed for %s:  %s\n",
            dv->devname, strerror(errno));
        if (sysfd >= 0)
            close(sysfd);
        goto abort;
    }
    if (sysfd >= 0)
        close(sysfd);
    sysfd = -1;
    count++;
    if (verbose >= 0)
        pr_err("set %s faulty in %s\n",
            dv->devname, devname);
    break;

Observe a chamada write(sysfd, "faulty", 6) . sysfd é uma variável definida anteriormente no arquivo: sysfd = sysfs_open(fd2devnm(fd), dname, "block/dev");

sysfs_open() é uma função do este arquivo :

int sysfs_open(char *devnm, char *devname, char *attr)
{
    char fname[50];
    int fd;

    sprintf(fname, "/sys/block/%s/md/", devnm);
    if (devname) {
        strcat(fname, devname);
        strcat(fname, "/");
    }
    strcat(fname, attr);
    fd = open(fname, O_RDWR);
    if (fd < 0 && errno == EACCES)
        fd = open(fname, O_RDONLY);
    return fd;
}

Se você seguir as funções, descobrirá que mdadm /dev/md0 -f /dev/sdb1 basicamente faz isso:

echo "faulty" > /sys/block/md0/md/dev-sdb1/block/dev

Esta solicitação estará aguardando e não será processada imediatamente porque /dev/md0 está bloqueado.

3. Um tempo limite pode ser configurado para que md automaticamente falhe em uma unidade que não está respondendo aos comandos ATA?

Sim. Na verdade, por padrão, o tempo limite é de 30 segundos :

root@node51 [~]# cat /sys/block/sdb/device/timeout
30

O problema com sua suposição era que sua unidade estava realmente ocupada executando um comando ATA (por 188 minutos), então não foi o tempo limite.

Para mais detalhes, consulte o Documentação de tratamento de erros SCSI do kernel Linux .

4. Por que o md continua usando um dispositivo com dados inválidos?

Quando o Apagamento Seguro ATA terminou, a unidade não relatou nenhum problema, como um comando cancelado, por isso md não tinha motivos para suspeitar que havia um problema.

Além disso, no seu caso de usar partições como dispositivos RAID em vez de discos inteiros, a tabela de partições na memória do kernel não foi informada de que a partição na unidade limpa desapareceu, então md continuaria acessando o seu /dev/sdb1 como se nada estivesse errado.

Isso é da md man page :

Scrubbing and Mismatches

As storage devices can develop bad blocks at any time it is valuable to regularly read all blocks on all devices in an array so as to catch such bad blocks early. This process is called scrubbing.

md arrays can be scrubbed by writing either check or repair to the file md/sync_action in the sysfs directory for the device.

Requesting a scrub will cause md to read every block on every device in the array, and check that the data is consistent. For RAID1 and RAID10, this means checking that the copies are identical. For RAID4, RAID5, RAID6 this means checking that the parity block is (or blocks are) correct.

Podemos inferir a partir disso que a paridade não é normalmente verificada em todos os discos lidos. (Além disso, verificar a paridade em cada leitura seria muito desgastante no desempenho, aumentando as transações necessárias apenas para concluir uma leitura e execução da comparação da paridade com a leitura de dados.)

Em operação normal, md apenas assume que os dados que está lendo são válidos, deixando-os vulneráveis a corrupção silenciosa de dados . No seu caso, você teve uma unidade inteira de dados corrompidos silenciosamente porque você limpou a unidade.

Seu sistema de arquivos não estava ciente da corrupção. Você viu erros de entrada / saída no nível do sistema de arquivos porque o sistema de arquivos não conseguia entender por que tinha dados incorretos.

Para evitar a corrupção silenciosa de dados, primeiro, nunca faça o que você fez novamente . Em segundo lugar, considere o uso do ZFS , um sistema de arquivos que se concentra na integridade dos dados e detecta e corrige a corrupção de dados silenciosa.

    
por 29.07.2015 / 08:41