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.