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:


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

Libguestfs mailing list

Reply via email to