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 filefragou 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, 10Gem tamanho com um 2Gfuro. Possui duas extensões, a primeira cobertura 0-1048575e 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 hdparmsão as mesmas, apenas exibidas de maneira diferente (a primeira extensão abrange 8388608setores de 512 bytes a partir de 0, por isso é 0-4294967295bytes, portanto o furo é 4294967296-6442450944em 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-1572864buraco com ddcomo mostrado acima, pode ser feito através da adição de adequados (idênticas) seek/ skipvalores e count. Observe que o bs=foi adaptado para usar os 4ksetores, conforme usado filefragacima. (Para bs=1M, você teria que adaptar os valores de busca / pular / contagem para refletir 1Mblocos 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/zerovez de ler o buraco do arquivo em si (o que também produzirá zeros), é mais seguro ler o arquivo de sparsefilequalquer 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 ddsoluçã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, fallocateparece 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. filefragmostra 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 usarfallocateno Linux para evitar a necessidade de gravar esses bytes NUL se tudo o que você deseja é o espaço a ser alocado.