Quero construir um NAS usando mdadm para RAID e btrfs para detecção de bitrot. Eu tenho uma configuração bastante básica, combinando 3 discos de 1 TB com mdadm para um RAID5, além do btrfs.
Eu sei que o mdadm não pode reparar o bitrot. Ele só pode me dizer quando há incompatibilidades, mas não sabe quais dados estão corretos e quais estão com defeito. Quando digo ao mdadm para reparar meu md0 depois de simular o bitrot, ele sempre reconstrói a paridade. O Btrfs usa somas de verificação para saber quais dados estão com defeito, mas não pode reparar os dados, pois não consegue ver a paridade.
No entanto, posso executar uma limpeza btrfs e ler o syslog para obter o deslocamento dos dados que não correspondem à sua soma de verificação. Posso então traduzir esse deslocamento para um disco e um deslocamento nesse disco, porque conheço o deslocamento inicial dos dados de md0 (2048 * 512), o tamanho do bloco (512K) e o layout (simétrico à esquerda). O layout significa que na minha primeira camada a paridade está no terceiro disco, na segunda camada no segundo disco e na terceira camada no primeiro disco.
Combinando todos esses dados e mais alguns btrfs sobre o conhecimento do formato do disco, posso calcular exatamente qual parte do disco está com defeito. No entanto, não consigo encontrar uma maneira de dizer ao mdadm para reparar esse pedaço específico.
Eu já escrevi um script que troca a paridade e o pedaço defeituoso usando o comando dd, depois inicia um reparo com mdadm e depois os troca de volta, mas esta não é uma boa solução e eu realmente gostaria que o mdadm marcasse este setor como ruim e não use novamente. Como começou a apodrecer, há grandes chances de que isso aconteça novamente.
Minha pergunta é:existe alguma maneira de dizer ao mdadm para reparar um único pedaço (que não é a paridade) e possivelmente até marcar um setor do disco como ruim? Talvez criando um erro de leitura io?
(E eu sei que o ZFS pode fazer tudo isso sozinho, mas não quero usar memória ECC)
Editar:esseA pergunta/resposta é sobre como o btrfs RAID6 é instável e como o ZFS é muito mais estável/utilizável. Isso não responde à minha pergunta sobre como reparar um único pedaço defeituoso conhecido com o mdadm.
Responder1
Não consigo encontrar uma maneira de dizer ao mdadm para reparar esse pedaço específico.
Isso porque quando há corrupção silenciosa de dados, o md não tem informações suficientes para saber qual bloco está corrompido silenciosamente.
Convido você a ler meuresposta à pergunta nº 4 ("Por que md
continua usando um dispositivo com dados inválidos?") aqui, o que explica isso com mais detalhes.
Para piorar a situação para o layout proposto,se um bloco de paridade sofrer corrupção silenciosa de dados, a camada Btrfs acima não poderá vê-lo! Quando um disco com o bloco de dados correspondente falha e você tenta substituí-lo, o md usará a paridade corrompida e corromperá irreversivelmente seus dados. Somente quando o disco falhar o Btrfs reconhecerá a corrupção, mas você já perdeu os dados.
Isso ocorre porque md não lê blocos de paridade, a menos que o array esteja degradado.
Então, existe alguma maneira de dizer ao mdadm para reparar um único pedaço (que não é a paridade) e possivelmente até marcar um setor do disco como ruim? Talvez criando um erro de leitura io?
Para setores defeituosos que o disco rígido descobriu sozinho, o md pode lidar com isso facilmente porque o setor defeituoso é identificado pelo md.
Tecnicamente, você pode criar um setor defeituoso com hdparm --make-bad-sector
, mas como saber qual disco tem o bloco afetado pela corrupção silenciosa de dados?
Considere este exemplo simplificado:
Fórmula de paridade:PARITY = DATA_1 + DATA_2
+--------+--------+--------+
| DATA_1 | DATA_2 | PARITY |
+--------+--------+--------+
| 1 | 1 | 2 | # OK
+--------+--------+--------+
Agora vamos corromper cada um dos blocos silenciosamente com um valor de 3
:
+--------+--------+--------+
| DATA_1 | DATA_2 | PARITY |
+--------+--------+--------+
| 3 | 1 | 2 | # Integrity failed – Expected: PARITY = 4
| 1 | 3 | 2 | # Integrity failed – Expected: PARITY = 4
| 1 | 1 | 3 | # Integrity failed – Expected: PARITY = 2
+--------+--------+--------+
Se você não tivesse a primeira tabela para examinar, como saberia qual bloco estava corrompido?
Você não pode ter certeza.
É por isso que Btrfs e ZFS são blocos de soma de verificação. É preciso um pouco mais de espaço em disco, mas essas informações extras permitem que o sistema de armazenamento descubra qual bloco está.
DeArtigo do blog de Jeff Bonwick "RAID-Z":
Sempre que você lê um bloco RAID-Z, o ZFS o compara com sua soma de verificação. Se os discos de dados não retornarem a resposta correta, o ZFS lê a paridade e então faz a reconstrução combinatória para descobrir qual disco retornou dados incorretos.
Para fazer isso com o Btrfs no md, você teria que tentar recalcular cada bloco até que a soma de verificação corresponda ao Btrfs, um processo demorado sem nenhuma interface fácil exposta ao usuário/script.
Eu sei que o ZFS pode fazer tudo isso sozinho, mas não quero usar memória ECC
Nem o ZFS nem o Btrfs sobre md dependem ou sequer conhecem a memória ECC. A memória ECC detecta apenas corrupção silenciosa de dados na memória, portanto, é independente do sistema de armazenamento.
Eu recomendei ZFS sobre Btrfs para RAID-5 e RAID-6 (análogo ao ZFS RAID-Z e RAID-Z2, respectivamente) antes emBtrfs sobre mdadm raid6?eFalha no dispositivo no md RAID quando o ATA para de responder, mas gostaria de aproveitar esta oportunidade para descrever mais algumas vantagens do ZFS:
- Quando o ZFS detecta corrupção silenciosa de dados, ela é corrigida automática e imediatamente no local, sem qualquer intervenção humana.
- Se você precisar reconstruir um disco inteiro, o ZFS apenas "resilverá" os dados reais, em vez de executar desnecessariamente todo o dispositivo de bloco.
- ZFS é uma solução completa para volumes lógicos e sistemas de arquivos, o que torna seu gerenciamento menos complexo do que o Btrfs sobre md.
- RAID-Z e RAID-Z2 são confiáveis e estáveis, ao contrário
- Btrfs em md RAID-5/RAID-6, que oferece apenas detecção de erros em blocos de dados corrompidos silenciosamente (além de blocos de paridade corrompidos silenciosamente podem passar despercebidos até que seja tarde demais) e nenhuma maneira fácil de corrigir erros, e
- Btrfs RAID-5/RAID-6, que "tem vários bugs sérios de perda de dados".
- Se eu corrompesse silenciosamente um disco inteiro com o ZFS RAID-Z2, não perderia nenhum dado, enquanto no md RAID-6,Na verdade, perdi 455.681 inodes.
Responder2
Encontrei uma maneira de criar um erro de leitura para o mdadm.
Com dmsetup você pode criar dispositivos lógicos a partir de tabelas.
Os dispositivos são criados carregando uma tabela que especifica um alvo para cada setor (512 bytes)
Nessas tabelas você pode especificar deslocamentos que devem retornar um erro de IO, por exemplo:
0 4096 linear /dev/sdb 0
4096 1 error
4097 2093055 linear /dev/sdb 4097
Isso cria um dispositivo (1 GB) com um erro no deslocamento 4096*512.