Em face disso, é simples dd
:
dd if=sparsefile of=sparsefile conv=notrunc bs=1M
Isso lê o arquivo inteiro e grava todo o conteúdo nele.
Para escrever apenas o próprio furo, primeiro você precisa determinar onde estão esses orifícios. Você pode fazer isso usando filefrag
ou hdparm
:
filefrag:
# filefrag -e sparsefile
Filesystem type is: 58465342
File size of sparsefile is 10737418240 (2621440 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 1048575: 187357696.. 188406271: 1048576:
1: 1572864.. 2621439: 200704128.. 201752703: 1048576: 188406272: last,eof
sparsefile: 2 extents found
hdparm:
# hdparm --fibmap sparsefile
sparsefile:
filesystem blocksize 4096, begins at LBA 0; assuming 512 byte sectors.
byte_offset begin_LBA end_LBA sectors
0 1498861568 1507250175 8388608
6442450944 1605633024 1614021631 8388608
Este arquivo de exemplo é, como você diz, 10G
em tamanho com um 2G
furo. Possui duas extensões, a primeira cobertura 0-1048575
e a segunda 1572864-2621439
, o que significa que o furo é 1048576-1572864
(em blocos de tamanho 4k, conforme mostrado filefrag
). As informações mostradas por hdparm
são as mesmas, apenas exibidas de maneira diferente (a primeira extensão abrange 8388608
setores de 512 bytes a partir de 0, por isso é 0-4294967295
bytes, portanto o furo é 4294967296-6442450944
em bytes.
Observe que você pode ser mostrado consideravelmente mais extensões de qualquer maneira, se houver alguma fragmentação. Infelizmente, nenhum dos comandos mostra os furos diretamente, e eu não conheço um que faça isso, então você deve deduzi-lo dos desvios lógicos mostrados.
Agora, preenchendo esse 1048576-1572864
buraco com dd
como mostrado acima, pode ser feito através da adição de adequados (idênticas) seek
/ skip
valores e count
. Observe que o bs=
foi adaptado para usar os 4k
setores, conforme usado filefrag
acima. (Para bs=1M
, você teria que adaptar os valores de busca / pular / contagem para refletir 1M
blocos de tamanho).
dd if=sparsefile of=sparsefile conv=notrunc \
bs=4k seek=1048576 skip=1048576 count=$((-1048576+1572864))
Embora você possa preencher buracos em /dev/zero
vez de ler o buraco do arquivo em si (o que também produzirá zeros), é mais seguro ler o arquivo de sparsefile
qualquer maneira, para que você não corrompa seus dados caso ocorra um deslocamento incorreto.
Nas versões mais recentes de GNU dd
, você pode manter um tamanho de bloco maior e especificar todos os valores em bytes:
dd if=sparsefile of=sparsefile conv=notrunc bs=1M \
iflag=skip_bytes,count_bytes oflag=seek_bytes \
seek=4294967296 skip=4294967296 count=$((-4294967296+6442450944))
filefrag
depois de executar isso:
# sync
# filefrag -e sparsefile
Filesystem type is: 58465342
File size of sparsefile is 10737418240 (2621440 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 1572863: 187357696.. 188930559: 1572864:
1: 1572864.. 2621439: 200704128.. 201752703: 1048576: 188930560: last,eof
sparsefile: 2 extents found
Devido à fragmentação, ainda existem duas extensões. No entanto, as compensações lógicas mostram que, desta vez, não há furo; portanto, o arquivo não é mais escasso.
Naturalmente, esta dd
solução é a abordagem muito manual das coisas. Se você precisar disso regularmente, seria fácil escrever um pequeno programa que preencha essas lacunas. Se ele já existe como uma ferramenta padrão, ainda não ouvi falar.
Existe uma ferramenta, afinal, fallocate
parece funcionar, de certa forma:
fallocate -l $(stat --format="%s" sparsefile) sparsefile
No entanto, finalmente, no caso do XFS, embora ele aloque área física para esse arquivo, na verdade não o zera. filefrag
mostra extensões como alocadas, mas não escritas.
2: 3.. 15: 7628851.. 7628863: 13: 7629020: unwritten
Isso não é bom o suficiente se a intenção é poder ler os dados corretos diretamente do dispositivo de bloco. Ele reserva apenas o espaço de armazenamento necessário para gravações futuras.
cat sparsefile 1<> sparsefile
. Você pode usarfallocate
no Linux para evitar a necessidade de gravar esses bytes NUL se tudo o que você deseja é o espaço a ser alocado.fallocate
. Tem--dig-holes
mas não--fill-holes
. No entanto, parece funcionar bem o suficiente quando você especifica o tamanho. Vou editar minha resposta.fallocate
têm um-z
que pode ser usado no Linux 3.14 e superior no ext4 e xfs (você precisaria executá-lo com-o
e-l
para todas as seções esparsas, suponho).-z
não mantém seus dados, se vocêdd