On Linux, given a sparse file, how to make it non-sparse, in place?
It could be copied with cp --sparse=never ...
, but if the file is say 10G and the hole is 2G
(that is the allocated space is 8G), how to make the filesystem allocate the remaining 2G without copying the original 8G to a new file?
Converting sparse file to non-sparse in place
filessparse-files
Best Answer
On the face of it, it's a simple
dd
:That reads the entire file, and writes the entire contents back to it.
In order to only write the hole itself, you first have to determine where those holes are. You can do that using either
filefrag
orhdparm
:filefrag:
hdparm:
This example file is, as you say,
10G
in size with a2G
hole. It has two extents, the first covering0-1048575
, the second1572864-2621439
, which means that the hole is1048576-1572864
(in 4k sized blocks, as shown byfilefrag
). The info shown byhdparm
is the same, just displayed differently (first extent covers8388608
512-byte sectors starting from 0 so it's0-4294967295
bytes, so the hole is4294967296-6442450944
in bytes.Note that you may be shown considerably more extents anyway if there is any fragmentation. Unfortunately, neither command shows the holes directly, and I don't know one that does such, so you have to deduce it from the logical offsets shown.
Now, filling that
1048576-1572864
hole withdd
as shown above, can be done by adding appropriate (identical)seek
/skip
values andcount
. Note that thebs=
was adapted to use the4k
sectors as used byfilefrag
above. (Forbs=1M
, you'd have to adapt the seek/skip/count values to reflect1M
sized blocks).While you could fill holes with
/dev/zero
instead of reading the hole of the file itself (which will also just yield zeroes), it is safer to read from thesparsefile
anyway so you won't corrupt your data in case you got an offset wrong.In newer versions of
GNU dd
, you may stick to a larger blocksize and specify all values in bytes:filefrag
after running that:Due to fragmentation, it's still two extents. However, the logical offsets show that this time, there is no hole, so the file is no longer sparse.
Naturally, this
dd
solution is the very manual approach to things. If you need this on a regular basis, it would be easy to write a small program that fills such gaps. If it already exists as a standard tool, I haven't heard of it yet.There is a tool after all,
fallocate
seems to work, after a fashion:However at last in case of XFS, while it does allocate physical area for this file, it does not actually zero it out.
filefrag
shows such extents as allocated, but unwritten.This is not good enough if the intent is to be able to read the correct data directly from the block device. It only reserves the storage space needed for future writes.