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
).