Resumo TL; DR : traduza um número de setor MD em deslocamentos dentro do /dev/mdX
dispositivo e como investigá-lo xfs_db
. O número do setor é de sh->sector
no linux/drivers/md/raid5.c:handle_parity_checks5()
.
Não conheço MD internals, portanto não sei exatamente o que fazer com a saída do printk
log adicionado.
As compensações nos dispositivos componentes (para dd
ou um editor / visualizador hexadecimal) também seriam interessantes.
Suponho que devo perguntar isso na lista de discussão sobre ataques Linux. É apenas para assinantes ou posso postar sem assinar?
Eu tenho xfs diretamente em cima do MD RAID5 de 4 discos na minha área de trabalho (sem LVM). Uma limpeza recente detectou um valor diferente de zero mismatch_cnt
(8, de fato, porque o md opera em páginas de 4kiB por vez).
Este é um RAID5, não RAID1 / RAID10, onde mismatch_cnt
! = 0 pode ocorrer durante a operação normal . (Os outros links na parte inferior desta página wiki podem ser úteis para algumas pessoas.)
Eu poderia apenas cegamente repair
, mas não teria idéia de qual arquivo verificar se havia uma possível corrupção, além de perder a chance de escolher qual caminho reconstruir. A resposta de Frostschutz em uma pergunta semelhante é a única sugestão que encontrei para retornar a uma diferença no sistema de arquivos. É complicado e lento, e eu prefiro usar algo melhor para reduzi-lo a alguns arquivos primeiro.
Patch do kernel para adicionar log
Estranhamente, o recurso de verificação do md não informa onde um erro foi encontrado . Eu adicionei um printk
no md / raid5.c para fazer login sh->sector
noif
ramo que incrementos mddev->resync_mismatches
emhandle_parity_checks5()
(pequeno pedaço publicada no github , originalmente baseado no 4.5-RC4 do kernel.org.) Para que isso seja ok para uso geral, que provavelmente seria necessário evite inundar os logs nos reparos com muitas incompatibilidades (talvez apenas registre se o novo valor resync_mismatches
for <1000?). Também talvez faça logon apenas check
e não repair
.
Tenho certeza de que estou registrando algo útil (mesmo que eu não conheça o MD internals!), Porque a mesma função imprime esse número de setor no caso de tratamento de erros doswitch
.
Compilei meu kernel modificado e o inicializei, depois executei novamente a verificação:
[ 399.957203] md: data-check of RAID array md125
...
[ 399.957215] md: using 128k window, over a total of 2441757696k.
...
[21369.258985] md/raid:md125: check found mismatch at sector 4294708224 <-- custom log message
[25667.351869] md: md125: data-check done.
Agora não sei exatamente o que fazer com esse número de setor. Existe sh->sector * 512
um endereço linear dentro /dev/md/t-r5
(aka /dev/md125
)? É um número de setor em cada dispositivo componente (portanto, refere-se a três dados e um setor de paridade)? Eu estou supondo o último, uma vez que uma incompatibilidade de paridade no RAID5 significa que os setores N-1 do dispositivo md estão em perigo, deslocados um do outro pela unidade de distribuição. O setor 0 é o início do dispositivo componente ou é o setor após o superbloco ou algo assim? Havia mais informações handle_parity_checks5()
que eu deveria ter calculado / registrado?
Se eu quisesse obter apenas os blocos incompatíveis, isso está correto?
dd if=/dev/sda6 of=mmblock.0 bs=512 count=8 skip=4294708224
dd if=/dev/sdb6 of=mmblock.1 bs=512 count=8 skip=4294708224
dd if=/dev/sda6 of=mmblock.2 bs=512 count=8 skip=4294708224
dd if=/dev/sdd of=mmblock.3 bs=512 count=8 skip=4294708224 ## not a typo: my 4th component is a smaller full-disk
# i.e.
sec_block() { for dev in {a,b,c}6 d; do dd if=/dev/sd"$dev" of="sec$1.$dev" skip="$1" bs=512 count=8;done; }; sec_block 123456
Acho que não, porque recebo 4k de zeros dos quatro componentes do ataque e 0^0 == 0
, portanto, essa deve ser a paridade correta, certo?
Outro lugar que vi menção ao uso de endereços de setor no md é para sync_min
e sync_max
(no sysfs). Neil Brown na lista de ataques Linux , em resposta a uma pergunta sobre uma falha na unidade com números de setor dehdrecover
onde Neil usou o número de setor de disco completo como um número de setor MD. Isso não está certo, está? Os números do setor md não seriam relativos aos dispositivos componentes (partições nesse caso), e não ao dispositivo completo do qual a partição faz parte?
setor linear para o nome do arquivo XFS:
Antes de perceber que o número do setor md provavelmente era para os componentes, não para o dispositivo RAID, tentei usá-lo em somente leitura xfs_db
:
A breve sugestão de Dave Chinner sobre como descobrir como o XFS está usando um determinado bloco não parecia funcionar para mim. (Eu esperaria algum tipo de resultado, para algum setor, pois o número não deve estar além do final do dispositivo, mesmo que não seja o setor incompatível)
# xfs_db -r /dev/md/t-r5
xfs_db> convert daddr 4294708224 fsblock
0x29ad5e00 (699227648)
xfs_db> blockget -nv -b 699227648
xfs_db> blockuse -n # with or without -c 8
must run blockget first
Hã? O que eu estou fazendo errado aqui? Eu acho que isso deve ser uma pergunta separada. Vou substituí-lo por um link se / quando solicitar ou encontrar uma resposta para esta parte em outro lugar.
Meu RAID5 está essencialmente ocioso, sem atividade de gravação e leitura mínima (e noatime
, portanto, as leituras não estão produzindo gravações).
Coisas extras sobre minha configuração, nada de importante aqui
Muitos dos meus arquivos são de vídeo ou outros dados compactados que fornecem uma maneira eficaz de saber se os dados estão corretos ou não (somas de verificação internas no formato de arquivo ou apenas decodificação sem erros). Isso tornaria viável esse método de loopback somente leitura , uma vez que eu saiba qual arquivo verificar. Eu não queria executar uma comparação em quatro direções de todos os arquivos no sistema de arquivos para encontrar a incompatibilidade primeiro, no entanto, quando o kernel tem as informações necessárias durante a verificação e pode registrá-las facilmente.
meu /proc/mdstat
para minha matriz de dados em massa:
md125 : active raid5 sdd[3] sda6[0] sdb6[1] sdc6[4]
7325273088 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/4] [UUUU]
bitmap: 0/19 pages [0KB], 65536KB chunk
Está em partições em três unidades Toshiba de 3 TB e em uma unidade de energia verde (lenta) WD25EZRS não particionada que estou substituindo por outra Toshiba. (Usandomdadm --replace
para fazê-lo on-line sem falhas de redundância. Percebi, depois de uma cópia, que eu deveria verificar a integridade do RAID antes e depois, para detectar problemas. Foi quando eu detectei a incompatibilidade. É possível que já exista há muito tempo , desde que tive algumas falhas há quase um ano, mas não tenho registros antigos e o mdadm parece não enviar e-mails sobre isso por padrão (Ubuntu 15.10).
Meus outros sistemas de arquivos estão em dispositivos RAID10f2 criados a partir de partições anteriores nos três HDs maiores (e RAID0 para / var / tmp). O RAID5 é apenas para armazenamento em massa, não /home
ou /
.
Minhas unidades estão bem: as contagens de erros SMART são 0 em todos os contadores de blocos defeituosos em todas as unidades e os autotestes SMART curtos + longos foram aprovados.
quase duplicatas desta pergunta que não têm respostas:
- Quais blocos são incompatíveis em uma matriz md do Linux?
- http://www.spinics.net/lists/raid/msg49459.html
- MDADM mismatch_cnt> 0. Alguma maneira de identificar quais blocos estão em desacordo?
- Outras coisas já estão ligadas inline, mas a ideia de loopback somente leitura de frostschutz é mais notável .
- limpando na página RAID do wiki do Arch
fonte
mdadm -E /dev/xxx
..damaged
ou algo assim, em vez de apenas saber que provavelmente há um arquivo quebrado em algum lugar.Respostas:
TL; DR sh-> sector é o número de setores nos discos físicos após o início da seção de dados
Configuração
Aqui está uma configuração de teste simples para ilustrar:
Agora, para começar, obtenha um bloco diferente de zero e substitua-o
Verifique se o cache do dm / md está nivelado, parando / remontando a matriz e verifique:
Bloquear em discos
Ok, primeiro vamos verificar 16384 corresponde ao que escrevemos. Meu ataque tem uma faixa de 512k, então eu escrevi algo alinhado para facilitar a correspondência, escrevemos em
1024*10240
ie0xa00000
.Seu patch fornece as informações
16384
, uma coisa a ter em atenção é que os dados não começam em 0:É o
printf "%x\n" $(((4096+16384)*512))
que diz isso0xa00000
também. Boa.Bloquear em md
Agora, para chegar a esse ponto final, é realmente mais fácil: é simplesmente a posição dada nos horários do setor,
number_of_stripes
por exemplo, para mim, tenho 4 discos (3 + 1) e 3 faixas.Aqui, isso significa,
16384*3*512
por exemplo0x1800000
. Enchi o disco muito bem, então é fácil verificar apenas lendo o disco e procurando 1k de zeros:Bloquear em xfs
Legal. Vamos ver onde está o xfs agora.
16384*3
is49152
(daddr leva o número do setor):Certamente, os zeros estão nesse arquivo:
Se sobrescrevermos esse arquivo, os zeros desaparecerão em / dev / raidme / rd0 no deslocamento correto também (apenas coloque-o em outro arquivo). Se você escrever em / dev / raidme / rd0 novamente (certifique-se de parar / iniciar o array novamente), os zeros estão de volta. Parece bom.
Porém, há mais um problema: se o tamanho da faixa for tão grande quanto o meu aqui (512k), não teremos um único bloco para lidar, mas 1,5 MB de dados possíveis corrompidos ... Muitas vezes, único arquivo, mas você precisa verificar isso em xfs_db. Lembre-se de inode anteriormente era 2052.
Um bloco tem o tamanho de 4096 bytes aqui (consulte
xfs_info
), então nossos 1,5 MB são 384 blocos. Nosso segmento corrompido é o bloco 6144 a 6528 - bem dentro do primeiro segmento deste arquivo.Outra coisa a considerar seria extrair os blocos manualmente e verificar onde exatamente as somas de verificação não coincidem, o que, com sorte, fornecerá três pedaços menores para serem examinados.
Por fim, sobre o seu patch, eu não sou um desenvolvedor md, mas como um ex-usuário do mdadm raid5, eu ficaria muito interessado. Eu diria que definitivamente vale a pena o esforço para avançar um pouco. A limpeza que você mencionou pode ser útil e tenho certeza que os desenvolvedores terão alguns comentários depois que você enviar um patch, mas o md precisa ser mais detalhado sobre esses erros!
fonte
printf '%#x\n' $(( (259072+4294708224 )*512 ))
é0x20000000000
, o que obviamente não é uma coincidência. (Isso é 2TiB precisamente. Eu suspeito que algumas travessuras do grub-install ou algum tipo de coisa do MBR). Eu não teria notado isso se estivesse apenas olhando as compensações dentro do dispositivo MD para encontrar o arquivo afetado. (BTW, o%#x
formato adiciona o0x
prefixo para você.)xfs_db
apenas dizmust run blockget first
, mesmo que acabei de fazer (exatamente como postei na pergunta), depois de seguir o seu exemplo. Mesmo se eu usarblockget -v -n -b 12884124672
para atribuir um bloco específico. Eu useidd
ehexdump
descobri que, na verdade, existe uma incompatibilidade nesse bloco. Três são zero e o quarto tem um único bit definido em 1kiB na faixa de 512k. (Muito conveniente que eu não tenho que encontrar uma maneira de realmente XOR blocos para verificar a redundância.)daddr
primeiro (antes do blockget), não recebo uma mensagem de erro, apenas nenhuma saída deblockget -v -n
eblockuse -v -n
. Caso isso importe, meu xfsprogs é o 3.2.1ubuntu1 e estou usando o Linux 4.2.0-36-generic (não o meu kernel -rc corrigido). Meu FS está usandocrc=1 isize=512
,naming =version 2 bsize=4096 ascii-ci=0 ftype=1
find -exec xfs_bmap -vpl {} +
para procurar um arquivo contendo o bloco conhecido.