On 2/11/20 4:52 AM, Richard W.M. Jones wrote:
On Mon, Feb 10, 2020 at 03:43:58PM -0600, Eric Blake wrote:
@@ -214,6 +217,52 @@ file_open (int readonly) h->can_fallocate = true; h->can_zeroout = h->is_block_device;
+ h->can_extents = false; + h->init_sparse = false; + h->init_zero = false; +#ifdef SEEK_HOLE
+ else if (r == statbuf.st_size) { + nbdkit_debug ("extents enabled, image currently all data"); + } + else { + nbdkit_debug ("extents enabled, image includes data before hole"); + h->init_sparse = true; + } + } + } + }
In the non-block case, can't we stat(2) the file and look at statbuf.st_blocks?
True. In fact, we already did do fstat(), so the information is already there. Note that st_blocks == 0 proves a file is sparse. But POSIX says st_block is not necessarily using the same units as st_blksize, so checking st_block * st_blksize < st_size is NOT necessarily evidence that a file is sparse. What's worse, there are some file systems where first- and second-level indirect blocks are used for large files, and where those indirects are counted towards st_block (but NOT towards st_size), so it is possible to have a sparse file where st_block * st_blksize > st_size but the file is still sparse. In short, proving that a file has holes is easy with lseek(SEEK_HOLE), but only a best-guess heuristic with stat() data. That said, you're right that it is at least worth adding the heuristics in the !SEEK_HOLE case.
+requires nbdsh -c 'exit (not hasattr (h, "get_init_flags"))'
Not wrong, but it's easier to do it like this:
https://github.com/libguestfs/nbdkit/blob/5e4745641bb4676f607fdb3f8750dbf6e9...
Thanks, that is cleaner. I will update it (along with the updates required by renaming it to two "is_init_*" functions) (affects several patches in this series). -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3226 Virtualization: qemu.org | libvirt.org