Punching holes on block device uses blkdev_issue_zeroout() with BLKDEV_ZERO_NOFALLBACK but there is no guarantee that this is fast enough for pre-zeroing an entire device.
Zeroing block device can be slow as writing zeroes or 100 times faster, depending on the storage. There is no way to tell if zeroing it fast enough. The kernel BLKDEV_ZERO_NOFALLBACK flag does not mean that the operation is fast; it just means that the kernel will not fall back to manual zeroing. Here is an example converting 10g image with 8g of data to block device: $ ./qemu-img info test.img image: test.img file format: raw virtual size: 10 GiB (10737418240 bytes) disk size: 8 GiB $ time ./qemu-img convert -f raw -O raw -t none -T none -W test.img /dev/test/lv1 Before: real 1m20.483s user 0m0.490s sys 0m0.739s After: real 0m55.831s user 0m0.610s sys 0m0.956s Signed-off-by: Nir Soffer <[email protected]> --- block/file-posix.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/block/file-posix.c b/block/file-posix.c index 3ab8f5a0fa..cd2e409184 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -1621,6 +1621,16 @@ static int handle_aiocb_write_zeroes_unmap(void *opaque) /* First try to write zeros and unmap at the same time */ #ifdef CONFIG_FALLOCATE_PUNCH_HOLE + /* + * The block device fallocate() implementation in the kernel does set + * BLKDEV_ZERO_NOFALLBACK, but it does not guarantee that the operation is + * fast so we can't call this if we have to avoid slow fallbacks. + */ + if (aiocb->aio_type & QEMU_AIO_BLKDEV && + aiocb->aio_type & QEMU_AIO_NO_FALLBACK) { + return -ENOTSUP; + } + int ret = do_fallocate(s->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, aiocb->aio_offset, aiocb->aio_nbytes); if (ret != -ENOTSUP) { -- 2.25.4
