ddrescue, “tamanho no disco” menor que o tamanho total, com possível impacto no desempenho ao gravar em NTFS

0

A história de fundo está na minha pergunta anterior e minha própria resposta .

Em um momento eu tive duas imagens parciais criadas por ddrescue : um arquivo no sistema de arquivos NTFS e outro no ext4.

Eu tinha notado bem no começo do processo que o "tamanho no disco" para ambas as imagens era bem menor que o tamanho total, indicando (se não me engano) que esses arquivos foram escritos como "esparsos", ou seja que os dados vazios não foram realmente alocados nos volumes correspondentes, apenas os dados que já haviam sido resgatados foram contabilizados. Mas em momento algum usei a opção -S nos meus comandos ddrescue , o que especifica que o arquivo de saída deve ser escrito como "esparso".

Side note: O que eu fiz foi usar o -R switch ("reverso") no começo, imaginando que iria alocar todo o tamanho do HDD de entrada imediatamente (a idéia era que isso resultaria em uma saída “mais limpa”, gravando todos os dados sequencialmente na partição receptora, para preservar a integridade do arquivo de imagem mesmo se algo desse errado com o sistema de arquivos e eu teria que recuperar a recuperação…); ele realmente aumentou o tamanho exibido do arquivo para 931,5 GB, mas na verdade o “tamanho no disco” foi aumentado apenas pela pequena quantidade de dados que foi copiada durante essa etapa.

Portanto, a questão principal seria: como essa dispersão pode ser explicada? Por que a cópia ddrescue não é sequencial por padrão?

Então, como eu tinha duas imagens parciais, ambas contendo alguns dados válidos ausentes do outro, fiz o seguinte:

  • Eu tentei copiar as áreas resgatadas da segunda imagem na partição ext4, ausente na primeira imagem, para a primeira imagem na partição NTFS, que deveria ter sido muito rápida, ambas as imagens no mesmo disco rígido saudável de 2 TB (um Seagate ST2000DX001 com uma velocidade máxima de gravação próxima a 200MB / s). Mas descobriu-se que era muito lento: apenas 660 KB / s.
  • Então eu parei e fiz o oposto: eu fiz ddrescue copiar as áreas resgatadas da primeira imagem (em NTFS), faltando na segunda imagem, para aquela segunda imagem (no ext4). E agora obtive uma taxa de cópia de 43.000KB / s ou 43MB / s, que foi consideravelmente maior e mais próxima de uma taxa de cópia normal dentro do mesmo HDD dessa classe e capacidade.

A segunda pergunta: esse comportamento estranho poderia estar relacionado ao problema de desempenho que senti ao gravar em NTFS? O driver Linux NTFS tem problemas para lidar com grandes arquivos “esparsos”?

    
por GabrielB 09.09.2017 / 04:40

2 respostas

1

Esta resposta investiga o comportamento de ddrescue para resolver a questão principal. Se você não está interessado em testar o procedimento, então você pode pular para as minhas conclusões e interpretação perto do final.

Testbed

$ uname -a
Linux foo 4.2.0-27-generic #32~14.04.1-Ubuntu SMP Fri Jan 22 15:32:26 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

$ cat /etc/issue
Ubuntu 14.04.5 LTS \n \l

$ ddrescue -V
GNU ddrescue 1.17
…

O sistema de arquivos é o btrfs; não importa, contanto que suporte arquivos esparsos.

Teste

No começo eu tenho 8 MiB de dados aleatórios:

dd if=/dev/urandom of=random.chunk bs=1M count=8

Então eu criei um dispositivo de loopback e lembrei do nome dele:

loopdev='sudo losetup -f --show random.chunk'

Em seguida, criei outro dispositivo que consistia em

  • pedaço 0: ilegível, 1 MiB
  • pedaço 1: zeros, 2 MiB
  • pedaço 2: ilegível, 4 MiB
  • trecho 3: dados de random.chunk , 8 MiB
  • bloco 4: ilegível, 16 MiB

O código (usa a sintaxe aqui do documento ):

sudo dmsetup create mydevice << EOF
    0  2048 error
 2048  4096 zero
 6144  8192 error
14336 16384 linear $loopdev 0
30720 32768 error
EOF

Confirmei com gdisk -l /dev/mapper/mydevice que o tamanho total é de 31 MiB como deveria ser.

A leitura real é feita com:

ddrescue     /dev/mapper/mydevice  normal.raw  normal.log
ddrescue -R  /dev/mapper/mydevice normalR.raw normalR.log
ddrescue -S  /dev/mapper/mydevice  sparse.raw  sparse.log
ddrescue -RS /dev/mapper/mydevice sparseR.raw sparseR.log

E os resultados de ls -hls *.raw são

 10M -rw-rw-r-- 1 kamil kamil 15M Sep 10 00:37 normal.raw
 10M -rw-rw-r-- 1 kamil kamil 15M Sep 10 00:37 normalR.raw
8.0M -rw-rw-r-- 1 kamil kamil 15M Sep 10 00:37 sparse.raw
8.0M -rw-rw-r-- 1 kamil kamil 15M Sep 10 00:37 sparseR.raw

Para ter certeza, confirmei com cmp que todos os quatro arquivos são idênticos quando você os lê. Quatro arquivos de log continham o mesmo mapa de setores errôneos e saudáveis.

Observe que

  • 15 MiB significa que o último fragmento está faltando;
  • 10 MiB indica o pedaço 1 e o pedaço 3;
  • 8 MiB indica apenas o bloco 3.

Limpeza

sudo dmsetup remove mydevice
sudo losetup -d $loopdev
unset loopdev
rm random.chunk normal.raw normal.log normalR.raw normalR.log sparse.raw sparse.log sparseR.raw sparseR.log

Conclusões

  • Quando se trata de tamanho de arquivo, não importa se você lê em sentido inverso ( -R ) ou não.
  • O bloco ilegível no final do arquivo de entrada não contribui para o tamanho geral do arquivo de saída.
  • Os blocos ilegíveis que contribuem para o tamanho geral do arquivo são sempre esparsos (se o sistema de arquivos de destino suportar isso, é claro).
  • A opção -S afeta apenas os blocos de zeros que foram realmente lidos no arquivo de entrada.

Interpretação

Acima havia fatos. Esta seção é mais parecida com a minha opinião.

Parece que ddrescue tenta salvar seu espaço em disco sempre que puder fazer isso sem trabalho adicional. Quando você usa -S , a ferramenta precisa fazer alguns cálculos para verificar se um determinado bloco de dados é todo zeros. Se houver um erro de leitura, ele não precisará computar nada, pode tornar o fragmento esparso no arquivo de saída sem custo.

Solução

Você escreveu:

using the -R switch (“reverse”) at the beginning, figuring that it would allocate the whole size of the input HDD right away

Acabamos de ver que é uma suposição falsa. Na verdade, você descreveu o que o -p faz. ddrescue -p pré-aloca espaço no disco para o arquivo de saída. Quando fiz isso durante meus testes, o arquivo de saída tinha 31 MiB e não era esparso (mesmo com -S ).

    
por 10.09.2017 / 01:51
0

Eu fiz um teste diferente por conta própria.

- Eu criei um arquivo de log / map ddrescue de modelo simples contendo isto:

0x00000000  0x100000  ?
0x100000  0x3FE00000  +
0x3FF00000  0x100000  ?

(o que significa: dentro de um GB de dados no total, o primeiro e o último MB não foram tentados, o resto é considerado como "resgatado").

- Eu executei ddrescue com esse arquivo de log / map, usando este comando (com a imagem recuperada da recuperação daquele HDD de 1 TB como entrada, cortando a saída em 1 GB):

ddrescue -s 1073741824 [rescued_image_file] [test1GB] [test1GB.log]

O arquivo [test1GB] resultante tem um tamanho total de 1 GB como esperado, mas um “tamanho no disco” de 2 MB, o que significa que apenas os dados copiados (primeiro e último MB) foram alocados.

- Então eu corri o ddrescue com aquele arquivo de 1GB como entrada, sem template desta vez, primeiro sem e depois com o switch -S (“sparse writes”).

ddrescue [test1GB] [test1GB-NS] [test1GB-NS.log]
ddrescue -S [test1GB] [test1GB-S] [test1GB-S.log]

E parece que:

  • [test1GB-NS] (não esparso) tem um “tamanho no disco” de 1GB - então todo o arquivo foi alocado e copiado, mesmo os setores vazios; enquanto que ...
  • [test1GB-S] (sparse) tem um “tamanho no disco” de apenas 1,2 MB ou 1114112 bytes - o que significa que os setores vazios não foram alocados, mesmo aqueles contidos no primeiro e último MB.

Eu achei que “sparseness” era um conceito de tudo ou nada, assim como a compactação de arquivos, mas aparentemente existe algo como um arquivo “parcialmente esparso”, e de fato o ddrescue parece estar economizando espaço dessa forma - o que não é necessariamente uma vantagem (e pode realmente ter um impacto no desempenho); deve haver um switch para alocar o tamanho total do arquivo de saída on-the-fly (em oposição à pré-alocação que pode ser muito longa se a entrada for grande), assim como faz (obviamente) ao escrever diretamente para um dispositivo ou partição.

    
por 11.09.2017 / 16:19