qcow2: Stop overwriting compressed clusters one by one
commitbf3d78ae55ccb276f318168d39d17a36f25221b4
authorAlberto Garcia <berto@igalia.com>
Wed, 11 Sep 2019 15:16:26 +0000 (11 18:16 +0300)
committerKevin Wolf <kwolf@redhat.com>
Fri, 13 Sep 2019 10:18:37 +0000 (13 12:18 +0200)
tree8dc3fd5d4c30f13bfe284b9c2ca352e6ca5367c9
parentd90d5cae2b10efc0e8d0b3cc91ff16201853d3ba
qcow2: Stop overwriting compressed clusters one by one

handle_alloc() tries to find as many contiguous clusters that need
copy-on-write as possible in order to allocate all of them at the same
time.

However, compressed clusters are only overwritten one by one, so let's
say that we have an image with 1024 consecutive compressed clusters:

   qemu-img create -f qcow2 hd.qcow2 64M
   for f in `seq 0 64 65472`; do
      qemu-io -c "write -c ${f}k 64k" hd.qcow2
   done

In this case trying to overwrite the whole image with one large write
request results in 1024 separate allocations:

   qemu-io -c "write 0 64M" hd.qcow2

This restriction comes from commit 095a9c58ce12afeeb90c2 from 2008.
Nowadays QEMU can overwrite multiple compressed clusters just fine,
and in fact it already does: as long as the first cluster that
handle_alloc() finds is not compressed, all other compressed clusters
in the same batch will be overwritten in one go:

   qemu-img create -f qcow2 hd.qcow2 64M
   qemu-io -c "write -z 0 64k" hd.qcow2
   for f in `seq 64 64 65472`; do
      qemu-io -c "write -c ${f}k 64k" hd.qcow2
   done

Compared to the previous one, overwriting this image on my computer
goes from 8.35s down to 230ms.

Signed-off-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: John Snow <jsnow@redhat.com
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
block/qcow2-cluster.c