]> git.ipfire.org Git - thirdparty/qemu.git/commit - qemu-img.c
qemu-img: Speed up compare on pre-allocated larger file
authorEric Blake <eblake@redhat.com>
Thu, 12 Oct 2017 03:47:10 +0000 (22:47 -0500)
committerKevin Wolf <kwolf@redhat.com>
Thu, 26 Oct 2017 12:45:57 +0000 (14:45 +0200)
commit391cb1aacad155bea4270b863710bba9adabe311
treefcb547a220d3dbd1b1ee722cbeff8a70d3a9b0cc
parent7daddc615e694ede5dd75366e8a0407f2404ccd8
qemu-img: Speed up compare on pre-allocated larger file

Compare the following images with all-zero contents:
$ truncate --size 1M A
$ qemu-img create -f qcow2 -o preallocation=off B 1G
$ qemu-img create -f qcow2 -o preallocation=metadata C 1G

On my machine, the difference is noticeable for pre-patch speeds,
with more than an order of magnitude in difference caused by the
choice of preallocation in the qcow2 file:

$ time ./qemu-img compare -f raw -F qcow2 A B
Warning: Image size mismatch!
Images are identical.

real 0m0.014s
user 0m0.007s
sys 0m0.007s

$ time ./qemu-img compare -f raw -F qcow2 A C
Warning: Image size mismatch!
Images are identical.

real 0m0.341s
user 0m0.144s
sys 0m0.188s

Why? Because bdrv_is_allocated() returns false for image B but
true for image C, throwing away the fact that both images know
via lseek(SEEK_HOLE) that the entire image still reads as zero.
From there, qemu-img ends up calling bdrv_pread() for every byte
of the tail, instead of quickly looking for the next allocation.
The solution: use block_status instead of is_allocated, giving:

$ time ./qemu-img compare -f raw -F qcow2 A C
Warning: Image size mismatch!
Images are identical.

real 0m0.014s
user 0m0.011s
sys 0m0.003s

which is on par with the speeds for no pre-allocation.

Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
qemu-img.c