A primera vista, es un simple dd
:
dd if=sparsefile of=sparsefile conv=notrunc bs=1M
Eso lee todo el archivo y vuelve a escribir todo el contenido.
Para escribir solo el agujero en sí, primero debes determinar dónde están esos agujeros. Puede hacerlo usando filefrag
o 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 archivo de ejemplo es, como usted dice, 10G
de tamaño con un 2G
agujero. Tiene dos extensiones, la primera cubierta 0-1048575
, la segunda 1572864-2621439
, lo que significa que el agujero es 1048576-1572864
(en bloques de tamaño 4k, como se muestra en la figura filefrag
). La información que se muestra hdparm
es la misma, solo se muestra de manera diferente (la primera extensión cubre 8388608
sectores de 512 bytes comenzando desde 0, por lo que son 0-4294967295
bytes, por lo que el agujero está 4294967296-6442450944
en bytes.
Tenga en cuenta que de todos modos se le puede mostrar considerablemente más extensiones si hay alguna fragmentación. Desafortunadamente, ninguno de los comandos muestra los agujeros directamente, y no conozco uno que lo haga, por lo que debe deducirlo de las compensaciones lógicas que se muestran.
Ahora, llenando ese 1048576-1572864
agujero con el dd
que se muestra arriba, puede hacerse agregando los valores seek
/ idénticos y apropiados . Tenga en cuenta que se adaptó para usar los sectores como se utilizó anteriormente. (Para , tendría que adaptar los valores de búsqueda / omisión / recuento para reflejar bloques de tamaño).skip
count
bs=
4k
filefrag
bs=1M
1M
dd if=sparsefile of=sparsefile conv=notrunc \
bs=4k seek=1048576 skip=1048576 count=$((-1048576+1572864))
Si bien podría llenar los agujeros en /dev/zero
lugar de leer el agujero del archivo en sí (lo que también generará ceros), es más seguro leerlo de sparsefile
todos modos para que no corrompa sus datos en caso de que obtenga un desplazamiento incorrecto.
En las versiones más recientes de GNU dd
, puede mantener un tamaño de bloque más grande y especificar todos los valores en 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
después de ejecutar eso:
# 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
Debido a la fragmentación, todavía son dos extensiones. Sin embargo, los desplazamientos lógicos muestran que esta vez no hay agujeros, por lo que el archivo ya no es escaso.
Naturalmente, esta dd
solución es el enfoque muy manual de las cosas. Si necesita esto de forma regular, sería fácil escribir un pequeño programa que llene esos vacíos. Si ya existe como herramienta estándar, aún no he oído hablar de él.
Hay una herramienta, después de todo, fallocate
parece funcionar, de una manera:
fallocate -l $(stat --format="%s" sparsefile) sparsefile
Sin embargo, finalmente en el caso de XFS, si bien asigna un área física para este archivo, en realidad no lo pone a cero. filefrag
muestra las extensiones asignadas, pero no escritas.
2: 3.. 15: 7628851.. 7628863: 13: 7629020: unwritten
Esto no es lo suficientemente bueno si la intención es poder leer los datos correctos directamente desde el dispositivo de bloque. Solo reserva el espacio de almacenamiento necesario para futuras escrituras.
cat sparsefile 1<> sparsefile
. Es posible que pueda usarfallocate
en Linux para evitar tener que escribir esos bytes NUL si todo lo que desea es el espacio que se asignará.