Am 07.11.2025 um 10:18 hat Alberto Garcia geschrieben:
> During a rebase operation data is copied from the backing chain into
> the target image using a loop, and each iteration looks for a
> contiguous region of allocated data of at most IO_BUF_SIZE (2 MB).
> 
> Once that region is found, and in order to avoid partial writes, its
> boundaries are extended so they are aligned to the (sub)clusters of
> the target image (see commit 12df580b).
> 
> This operation can however result in a region that exceeds the maximum
> allowed IO_BUF_SIZE, crashing qemu-img.
> 
> This can be easily reproduced when the source image has a smaller
> cluster size than the target image:
> 
> base <- int <- active
> 
> $ qemu-img create -f qcow2 base.qcow2 4M
> $ qemu-img create -f qcow2 -F qcow2 -b base.qcow2 -o cluster_size=1M int.qcow2
> $ qemu-img create -f qcow2 -F qcow2 -b int.qcow2  -o cluster_size=2M 
> active.qcow2
> $ qemu-io -c "write -P 0xff 1M 2M" int.qcow2
> $ qemu-img rebase -F qcow2 -b base.qcow2 active.qcow2
> qemu-img: qemu-img.c:4102: img_rebase: Assertion `written + pnum <= 
> IO_BUF_SIZE' failed.
> Aborted
> 
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3174
> Fixes: 12df580b3b7f ("qemu-img: rebase: avoid unnecessary COW operations")
> Signed-off-by: Alberto Garcia <[email protected]>
> ---
>  qemu-img.c                 |  2 +-
>  tests/qemu-iotests/024     | 46 ++++++++++++++++++++++++++++++++++++++
>  tests/qemu-iotests/024.out | 27 ++++++++++++++++++++++
>  3 files changed, 74 insertions(+), 1 deletion(-)
> 
> diff --git a/qemu-img.c b/qemu-img.c
> index a7791896c1..454da88c73 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -4081,7 +4081,7 @@ static int img_rebase(const img_cmd_t *ccmd, int argc, 
> char **argv)
>              n += offset - QEMU_ALIGN_DOWN(offset, write_align);
>              offset = QEMU_ALIGN_DOWN(offset, write_align);
>              n += QEMU_ALIGN_UP(offset + n, write_align) - (offset + n);
> -            n = MIN(n, size - offset);
> +            n = MIN(n, MIN(size - offset, IO_BUF_SIZE));
>              assert(!bdrv_is_allocated(unfiltered_bs, offset, n, &n_alloc) &&
>                     n_alloc == n);

The fix itself looks ok.

> +$QEMU_IMG rebase -b "$BASE_NEW" -F $IMGFMT "$OVERLAY"
> +
> +echo "Verifying the data"
> +echo
> +
> +$QEMU_IO "$OVERLAY" -c "read -P 0x00  0 1M" | _filter_qemu_io
> +$QEMU_IO "$OVERLAY" -c "read -P 0xff 1M 2M" | _filter_qemu_io
> +$QEMU_IO "$OVERLAY" -c "read -P 0x00 2M 1M" | _filter_qemu_io

Here you mean 3M instead of 2M...

> +Verifying the data
> +
> +read 1048576/1048576 bytes at offset 0
> +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
> +read 2097152/2097152 bytes at offset 1048576
> +2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
> +Pattern verification failed at offset 2097152, 1048576 bytes

...which then fixes this failure.

> +read 1048576/1048576 bytes at offset 2097152
> +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
> +Offset          Length          File
> +0               0x400000        TEST_DIR/subdir/t.IMGFMT
> +
>  *** done

Thanks, I've fixed it up as below and applied the patch to my block
branch.

Kevin

diff --git a/tests/qemu-iotests/024 b/tests/qemu-iotests/024
index b59d825b42..021169b4a1 100755
--- a/tests/qemu-iotests/024
+++ b/tests/qemu-iotests/024
@@ -357,7 +357,7 @@ echo

 $QEMU_IO "$OVERLAY" -c "read -P 0x00  0 1M" | _filter_qemu_io
 $QEMU_IO "$OVERLAY" -c "read -P 0xff 1M 2M" | _filter_qemu_io
-$QEMU_IO "$OVERLAY" -c "read -P 0x00 2M 1M" | _filter_qemu_io
+$QEMU_IO "$OVERLAY" -c "read -P 0x00 3M 1M" | _filter_qemu_io

 $QEMU_IMG map "$OVERLAY" | _filter_qemu_img_map

diff --git a/tests/qemu-iotests/024.out b/tests/qemu-iotests/024.out
index cc18ee0290..1b7522ba71 100644
--- a/tests/qemu-iotests/024.out
+++ b/tests/qemu-iotests/024.out
@@ -264,8 +264,7 @@ read 1048576/1048576 bytes at offset 0
 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 read 2097152/2097152 bytes at offset 1048576
 2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Pattern verification failed at offset 2097152, 1048576 bytes
-read 1048576/1048576 bytes at offset 2097152
+read 1048576/1048576 bytes at offset 3145728
 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 Offset          Length          File
 0               0x400000        TEST_DIR/subdir/t.IMGFMT


Reply via email to