Descrição

Descrição

Descrição

Eu tenho uma matriz IMSM RAID 5 que contém 6 unidades SSD. Uma das unidades falhou há alguns meses e ainda não consegui substituí-la. (Sim, eu sei que às vezes sou preguiçoso. Por favor, não me julgue.) Mas já o removi do RAID.

Ontem, porém, outra unidade parece ter falhado. A matriz não é montada. Como até o BIOS falha ao construir o RAID, não consigo inicializar nada. Após uma inspeção mais detalhada, parece que a unidade está boa. Posso acessá-lo e fazer backups usando dd. Mas parece ter um registro MBR no início agora. Talvez algum processo tenha substituído o superbloco RAID por uma tabela MBR? Se for esse o caso, os dados ainda devem estar lá. Eu só preciso saber mdadmos metadados corretos. Quando penso nisso, a mesma coisa pode ter acontecido com a primeira unidade que supostamente "falhou". Uma vez que ainda era legível também. Mas não me preocupei em investigar naquela época.

No entanto, agora estou tentando encontrar uma maneira de remontar o array para acessar seus dados (se possível). Eu sei o tamanho do bloco, a ordem exata das unidades e o nível do RAID. Isso não deveria ser informação suficiente?

Algumas informações

A primeira coisa que fiz foi criar imagens das 5 unidades restantes usando dd(nomeado sd[a-e].backup). Também examinei todas as unidades usando --examinee salvei a saída. Você pode ler a saída emesta essência. Como você pode ver, o mdadm lê o cabeçalho MBR sdbe prossegue para a próxima unidade sem detectar nenhuma informação RAID. Para todas as outras unidades, o mdadm imprime os metadados corretos. Enquanto estamos nisso, aqui está o resultado decat /proc/mdstat

Personalities:
md127 : inactive sda[3](S) sdd[2](S) sde[1](S) sdc[0](S)
      13049 blocks super external:imsm

unused devices: <none>

O que eu tentei

  • Obviamente tentei "desligar e ligar novamente":
# mdadm --stop /dev/md127
mdadm: stopped /dev/md127
# mdadm --assemble /dev/md0 /dev/sdb missing /dev/sda /dev/sdc /dev/sde /dev/sdd
mdadm: Cannot assemble mbr metadata on /dev/sdb
mdadm: /dev/sdb has no superblock - assembly aborted
# mdadm --assemble --scan

Após a última chamada para mdadm, /proc/mdstatnovamente parece idêntico à saída acima.

Em seguida, criei dispositivos de loop somente leitura:

# losetup --show -rf /mnt/backup/sdX.backup
[...]
# losetup -a
/dev/loop1: [...] (/mnt/backup/sda.backup)
/dev/loop2: [...] (/mnt/backup/sdb.backup)
/dev/loop3: [...] (/mnt/backup/sdc.backup)
/dev/loop4: [...] (/mnt/backup/sdd.backup)
/dev/loop5: [...] (/mnt/backup/sde.backup)
  • Em seguida tentei usar --buildpois não requer nenhuma informação do superbloco e todos os metadados podem ser fornecidos manualmente:
# mdadm --build /dev/md0 --raid-devices=6 --level=5 --chunk=32 /dev/loop2 missing /dev/loop1 /dev/loop3 /dev/loop5 /dev/loop4
mdadm: Raid level 5 not permitted with --build

Mas aparentemente não tenho permissão para usar --buildno contexto de RAIDs de nível 5.

  • A próxima coisa que tentei foi usar, --assemblemas sem usar, as informações OROM sobre o RAID.
# IMSM_NO_PLATFORM=1 mdadm --assemble /dev/md0 /dev/loop2 missing /dev/loop1 /dev/loop3 /dev/loop5 /dev/loop4
mdadm: Cannot assemble mbr metadata on /dev/loop2
mdadm: /dev/loop2 has no superblock - assembly aborted

Isso teria sido muito fácil, eu acho. Posso, de alguma forma, dizer ao mdadm para assumir que esse loop2é o primeiro dispositivo dessa matriz e usar os metadados das outras unidades?

  • A última coisa que eu teria tentado seria remontar os dispositivos de loop como leitura e gravação e recriar o array. No entanto, todos os exemplos que encontrei (como esteouEste) suponha que o array foi criado com mdadm. Mas não foi. Ele foi inicialmente criado por um utilitário no BIOS e possui o formato IMSM ou Intel Rapid Storage. Acho que preciso ter um conhecimento mais detalhado sobre isso, como layout ou deslocamento de dados. Não tenho certeza de quais são os padrões do IMSM ou onde posso encontrá-los. Mas o mais importante é que estou preocupado com o fato de o formato de metadados do mdadm usar mais espaço e um superbloco maior do que o IMSM e sobrescrever os dados ao salvar os metadados. Talvez também seja possível recriar o array usando IMSM? Ou talvez seja possível armazenar os metadados externamente. Resumindo, não tenho ideia de como recriar manualmente um array IMSM com mdadm.

Outras perguntas sobre StackExchange

  • Estou ciente deessa questão. Mas não tenho certeza se isso pode ser aplicado à minha situação, pois estou usando o IMSM, que possui superblocos diferentes (se houver).
  • Eu também liessa questão. No entanto, trata-se de RAID 0 e a resposta sugere usar --buildo que não funciona com RAID 5.
  • Também estou cienteEste. Mas --forcenão é aplicável na minha situação, pois a unidade em questão não está apenas marcada como com falha ou fora de sincronia. E, novamente, não tenho certeza de como devo recriar o array especificamente com o IMSM.

Responder1

Eureka - Introdução

Então descobri como ter acesso aos meus dados novamente. Infelizmente não consegui recriar o array usando mdadm. O problema é que com o IMSM preciso primeiro criar um contêiner. Mas o contêiner não aceita dispositivos perdidos. Eu precisaria de todos os meus 6 discos rígidos originais, mas só tenho 5 no momento. Também não posso usar discos rígidos virtuais, pois eles precisam estar conectados ao controlador RAID. Além disso, não tenho certeza se ou como mdadmcomeçaria a sincronizar as unidades assim que eu criasse um volume. No entanto, encontrei uma maneira que envolve dmsetup. Consigo acessar todos os meus arquivos novamente.

Ao realizar vários backups das unidades para trabalhar com elas, também percebi que a única unidade que não faz mais parte da matriz às vezes falha com erros de E/S. Ainda consegui fazer backups, pois esses erros ocorriam apenas a cada terceira invocação do dd. Presumo que assim que ocorreu um dos erros de IO, a unidade provavelmente foi expulsa da matriz pelo IMSM e todos os seus metadados foram excluídos.

Também percebi que esta unidade era a primeira da matriz. Como tenho uma tabela GPT e como os dados do array começam no primeiro setor também é lógico que comece com um MBR. Portanto, o supersetor da unidade não foi substituído por um MBR. Sempre esteve lá.

Lendo os dados

Estou tentando dar aqui uma solução passo a passo que explica todos os comandos usados ​​no processo. Espero que isso ajude alguém por aí.

(Opcional) Faça um backup de todas as unidades

Isto não é estritamente necessário. Especialmente porque usaremos dispositivos de loop somente leitura posteriormente. No entanto, estou particularmente paranóico após uma grande falha na minha solução de armazenamento. Portanto, tento evitar ao máximo usar os dados reais. Além disso, o uso dos arquivos de backup mostra que esse método não requer discos rígidos ou BIOS originais. Tudo que você precisa é de uma imagem dd. Se você estiver pulando esta seção, certifique-se de realmente criar os dispositivos de loop na próxima seção como somente leitura ou você corre o risco de que seus dados fiquem ainda mais degradados e sejam perdidos para sempre.

No entanto, aqui está o comando para fazer backup do seu disco rígido. Você já deve estar familiarizado com dd. Mas caso você não execute este comando para cada disco rígido que faz parte do seu array:

# dd if=/dev/sdX of=/path/to/backups/sdX.img status=progress
# dd if=/dev/sdY of=/path/to/backups/sdY.img status=progress
# [...]

O arquivo de entrada if=/dev/sdXé o seu disco rígido. Substitua sdXpor sda, sdb, etc. O arquivo de saída of=/path/to/backups/sdX.imgaponta para a imagem que deve ser gravada. Novamente substitua sdXadequadamente. status=progressapenas informa à versão GNU do dd para imprimir o progresso atual no stderr.

Crie dispositivos de loop

A seguir vamos criar dispositivos de loop. Caso estejamos utilizando imagens de backup garante que sejam reconhecidas como arquivo de bloco. Embora isso possa não ser necessário. Mas em qualquer caso garante que a imagem só será lida já que estamos usando a flag somente leitura-r

# losetup --show -rf /path/to/backups/sdX.img
# losetup --show -rf /path/to/backups/sdY.img
[...]
  • -r: apenas leia do arquivo, não escreva nele
  • -f: use o próximo número disponível para o dispositivo de loop para que não tenhamos que adivinhar sozinhos.
  • --show: imprima o nome que você -frealmente escolheu. Isso geralmente é bastante útil. Embora estejamos imprimindo esses valores na próxima etapa de qualquer maneira.

Para obter uma boa visão geral dos dispositivos de loop que acabamos de criar, podemos usar o seguinte comando:

# losetup -a
/dev/loop1: [2129]:251265027 (/path/to/backups/sdX.img)
/dev/loop2: [2129]:251265027 (/path/to/backups/sdY.img)
[...]

Tente lembrar qual dispositivo de loop pertence a qual imagem.

Reunindo alguns metadados

Em seguida, precisamos descobrir algumas informações sobre o RAID. Especificamente, precisamos descobrir em qual setor o RAID inicia (especialmente no caso de um RAID de matriz), quantos setores ele abrange, qual é o tamanho e o layout do bloco e em que ordem as unidades foram adicionadas ao array.

Se houver pelo menos uma unidade que ainda faça parte da matriz e tenha metadados anexados, você poderá usá-la para recuperar a maioria das informações necessárias. Execute o seguinte comando em uma unidade sdXque ainda faz parte da matriz:

# mdadm --examine /dev/sdX
/dev/sdX:
          Magic : Intel Raid ISM Cfg Sig.
        Version : 1.3.00
    Orig Family : aa0b2c12
         Family : 48d867fb
     Generation : 0018f99c
     Attributes : All supported
           UUID : 0312fa14:fa8db3c2:2a76dc3f:299ed5b4
       Checksum : 084869b8 correct
    MPB Sectors : 6
          Disks : 6
   RAID Devices : 1

  Disk02 Serial : S21PNSBG710576N
          State : active
             Id : 00000000
    Usable Size : 488391936 (232.88 GiB 250.06 GB)

Bad Block Management Log:
       Log Size : 2040
      Signature : abadb10c
    Entry Count : 254

[NameOfYourArray]:
           UUID : 24b1e785:14f37ee5:41f6a4ab:d8b89e11
     RAID Level : 5
        Members : 6
          Slots : [__UUUU]
    Failed disk : 1
      This Slot : 2
    Sector Size : 512
     Array Size : 2441959424 (1164.42 GiB 1250.28 GB)
   Per Dev Size : 488392200 (232.88 GiB 250.06 GB)
  Sector Offset : 0
    Num Stripes : 7631124
     Chunk Size : 32 KiB
       Reserved : 0
  Migrate State : idle
      Map State : failed
    Dirty State : clean
     RWH Policy : off

A saída continua, mas você pode ignorar o resto. A saída mostrada acima produz as seguintes informações valiosas:

Sector Offset : 0       # Where the data starts
                        # (right at the first sector in my case)
Array Size : 2441959424 # Size of the volume (data) inside the array
Chunk Size : 32 KiB     # Size of a single chunk

Você pode até determinar onde está essa unidade específica em sua matriz.

This Slot : 2

Isso significa que esta é a terceira unidade da matriz. (O número do slot começa em zero.) Alternativamente, Disk## Serial : [...]também indica o número do slot:

Disk02 Serial : S21PNSBG710576N

Execute este comando para todas as unidades. Para aqueles que ainda produzem resultados válidos, anote o número do slot.

Há outro truque que você pode usar para determinar a primeira unidade do array. Como o RAID é gravado em blocos e não em bytes, os primeiros 32 KiB residem na primeira unidade. Os segundos 32 kiB na segunda unidade e assim por diante. Isso significa que a primeira unidade deve ter setores suficientes contendo o início da sua tabela de partições. O que significa que deve haver um MBR no início (mesmo quando você estiver usando GPT, pois ele começa com um MBR protetor). mdadm --examinejá informa que encontrou um MBR quando não há metadados. Mas você também pode usar fdisk -l.

No meu caso, consegui descobrir os números dos slots de quatro unidades por meio de seus metadados. Tive sorte porque a quinta unidade continha um MBR, então soube automaticamente que era a primeira. 5 de 6 unidades são suficientes para iniciar o array. Se você não souber os números exatos de slots de unidades suficientes, poderá tentar usar diferentes permutações até que esse método seja bem-sucedido.

O que significa que a ordem correta das minhas unidades e, portanto, dos meus dispositivos de loop é:

Slot Dirigir Dispositivo de loop
MBR (0) /dev/sdb /dev/loop2
1 ausente -
2 /dev/sda /dev/loop1
3 /dev/sdc /dev/loop3
4 /dev/sde /dev/loop5
5 /dev/sdd /dev/loop4

A última coisa a descobrir é o layout. Infelizmente mdadmnão nos dá nenhuma informação sobre isso. No entanto, quando olhamos paraDefinições de RAID da Intelparece que o layout do RAID 5 é sempre deixado assimétrico. Não tenho certeza se os arrays IMSM podem ser configurados com um layout diferente, mas parece improvável para mim. Se tudo isso não funcionar para você, tente layouts diferentes. Dar uma olhadana fontepara ler mais sobre os outros layouts.

Abaixo está uma visão geral de todos os níveis de RAID que o IMSM suporta. A palavra-chave dmsetup será usada no próximo capítulo.

Nível RAID Disposição Sintaxe dmsetup
0 N / D ataque0
1 N / D raid1
5 esquerda assimétrica raid5_la
10 padrão (sem 1E ou cópia) raid10

Se você não conseguir coletar metadados de nenhuma unidade, será necessário adivinhar os valores e/ou tentar combinações diferentes. Para ajudar, estes são os diferentes modos que o IMSM suporta:

Informações Valores possíveis
Níveis de RAID 0, 1, 5, 10
Tamanhos de pedaços 4 kiB, 8 kiB, 16 kiB, 32 kiB, 64 kiB, 128 kiB

Para o setor inicial e o tamanho, é melhor assumir zero e o tamanho da menor unidade na matriz vezes o número de unidades sem paridade, se você não tiver certeza. Você pode obter o tamanho em setores de uma unidade emitindo o seguinte comando:

blockdev --getsize /dev/sdX

Se seus dados não começarem do zero, você ainda poderá obter o deslocamento correto mais tarde,procurando por um cabeçalho de partiçãoou talvez até porprocurando por sistemas de arquivos.

Montando o array usando dmsetup

Infelizmente não há como fornecer os metadados manualmente quando você está usando o mdadm. A única exceção é para oNíveis de RAID 0 e 1 onde você pode usar--build:

mdadm --build /dev/md0 --raid-devices=2 --level=0 --chunk=32 /dev/loop0 /dev/loop1

Como não temos sorte aqui, precisamos usar uma ferramenta diferente. Portanto, vamos usar dmsetupem seu lugar. dmsetupé um comando que cria discos rígidos virtuais mapeados para unidades reais ou outras fontes. Esses mapeamentos consistem em diversas seções e cada seção pode ser mapeada para uma unidade diferente. No nosso caso precisamos apenas de uma seção e estamos mapeando para um RAID cujos metadados forneceremos manualmente.

Mas primeiro precisamos falar sobre números. Como determinamos anteriormente, o tamanho do bloco no meu caso era de 32 KiB. Porém dmsetuprequer setores. Em quase todos os casos, um setor equivale a 512 bytes. Se você quiser estar seguro, pode verificar o tamanho do setor com blockdev --getss /dev/sdX. No meu caso, isso significa 32 kiB / (512 bytes/sector) = 64 sectors. Já sabemos o tamanho dos dados na matriz em setores (ou seja, 2441959424). Mas há um problema. Eu tenho 6 dispositivos. Com um pedaço de paridade por faixa, o número de pedaços deve ser divisível por 5. Mas o número de setores não é divisível por 5. No meu caso, é pelo menos divisível o número de setores por pedaço. Mas nem tenho certeza se isso é garantido. Parece que os dados param na metade da última faixa. Infelizmente, o dmsetup não tolerará isso. Isso significa que precisamos arredondar para o número inteiro mais próximo que seja divisível por 5 unidades e por 64 setores (ajuste esses números de acordo com sua situação). No meu caso é: 2441959680. Isso significa que fdiskposso reclamar de um tamanho de unidade incorreto e de uma tabela de backup ausente. Mas podemos consertar isso truncando a imagem dd.

Agora crie um arquivo (por exemplo, table.txt) que conterá uma linha para uma seção.

<start> <size> raid <raid layout> 2 <chunk size> nosync <num devices>[ - /dev/loopN|-]*num_devices

Primeiro você tem que dar o início e o tamanho dos setores. O próximo argumento diz que este é um RAID. Para o layout RAID consulte a tabela na seção anterior. O “2” no próximo argumento significa dois parâmetros especiais para o RAID. O primeiro é o tamanho do pedaço. O segundo impedirá qualquer sincronização. Depois disso, você deve descrever suas unidades, primeiro fornecendo o número de dispositivos e, em seguida, fornecendo um par de metadados e caminho de dispositivo para cada dispositivo. Como não queremos fornecer nenhum metadado, usamos um travessão para indicar isso. Se o dispositivo estiver faltando, escrevemos dois travessões indicando que nem os metadados nem o dispositivo estão disponíveis. É aconselhável deixar de fora pelo menos um dispositivo se o nível do RAID permitir. Se você já suspeita que uma unidade pode conter dados defeituosos, escolha essa.

Por exemplo, no meu caso, o arquivo fica assim. Observe que o segundo dispositivo está faltando.

0 2441959680 raid raid5_la 2 64 nosync 6 - /dev/loop2 - - - /dev/loop1 - /dev/loop3 - /dev/loop5 - /dev/loop4

Agora execute o seguinte comando para criar um novo arquivo de bloco que mapeie nosso array:

# dmsetup create sdr /path/to/table.txt

Isso pode gerar vários erros de IO. Nesse caso, o tamanho dos setores provavelmente não era divisível pelo tamanho do pedaço. Você pode remover o arquivo de bloco para refazer a última etapa com o seguinte comando:

# dmsetup remove sdr

Agora vamos dar uma olhada neste arquivo de dispositivo recém-criado. Se você correr

# fdisk -l /dev/mapper/sdr

você deverá conseguir ver sua tabela de partições. Não se preocupe com os dois erros que aparecerão se você tiver uma tabela GPT. A incompatibilidade de tamanho e a falta da tabela de backup se devem ao fato de termos escolhido um tamanho muito grande para nosso RAID.

O meu é assim:

Device                     Start        End    Sectors   Size Type
/dev/mapper/sdr-part1       2048     923647     921600   450M Windows recovery environment
/dev/mapper/sdr-part2     923648    1128447     204800   100M EFI System
/dev/mapper/sdr-part3    1128448    1161215      32768    16M Microsoft reserved
/dev/mapper/sdr-part4    1161216  679840003  678678788 323.6G Microsoft basic data
/dev/mapper/sdr-part5  679841792  680902655    1060864   518M Windows recovery environment
/dev/mapper/sdr-part6  680904704 2295472127 1614567424 769.9G Linux filesystem
/dev/mapper/sdr-part7 2295472128 2441957375  146485248  69.9G Linux swap

Usando a coluna inicial e setores nesta tabela podemos até montar algumas dessas partições. Observe que todos os números estão em setores e precisam ser convertidos em bytes multiplicando por 512.

# mount -o ro,noload,loop,offset=348623208448,sizelimit=826658521088 /dev/mapper/sdr /mnt

O que significa que minha partição Linux agora está montada em /mnt e posso navegar por todos os meus arquivos no romodo (ou seja, somente leitura). O noloadé necessário paraimpedir que o ext4 execute operações de gravação.

E agora finalmente faremos um backup completo usando dd.

# dd if=/dev/mapper/sdr of=/path/to/backups/raid.img status=progress

Lembra como criamos um RAID um pouco maior do que deveria? Podemos aproveitar esta oportunidade para corrigir esse erro truncando a imagem para o tamanho correto. O número de setores precisa ser convertido em bytes: 2441959424*512 = 1250283225088.

# truncate -s 1250283225088 /path/to/backups/raid.img

Agora fdisk -lnão reclama mais de incompatibilidade de tamanho.

informação relacionada