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
