diff --git a/qemu-img.c b/qemu-img.c index 87340a73c35199884eb669b9d5f319bbf1097883..926b5928c16d0cebfcd79141223fa10e446c795c 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -3944,7 +3944,7 @@ static int img_rebase(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); diff --git a/tests/qemu-iotests/024 b/tests/qemu-iotests/024 index 285f17e79f0c44d147c0a321a69658b6c5d35a7f..ca1fafc69b1e5a99c3cc4c2fbc10d92bd350d15c 100755 --- a/tests/qemu-iotests/024 +++ b/tests/qemu-iotests/024 @@ -315,6 +315,52 @@ echo $QEMU_IMG map "$OVERLAY" | _filter_qemu_img_map +# Check that the region to copy to the overlay during a rebase +# operation does not exceed the I/O buffer size. +# +# backing_new <-- backing_old <-- overlay +# +# Backing (new): -- -- -- -- <-- Empty image, size 4MB +# Backing (old):|--|ff|ff|--| <-- 4 clusters, 1MB each +# Overlay: |-- --|-- --| <-- 2 clusters, 2MB each +# +# The data at [1MB, 3MB) must be copied from the old backing image to +# the overlay. However the rebase code will extend that region to the +# overlay's (sub)cluster boundaries to avoid CoW (see commit 12df580b). +# This test checks that IO_BUF_SIZE (2 MB) is taken into account. + +echo +echo "=== Test that the region to copy does not exceed 2MB (IO_BUF_SIZE) ===" +echo + +echo "Creating backing chain" +echo + +TEST_IMG=$BASE_NEW _make_test_img 4M +TEST_IMG=$BASE_OLD CLUSTER_SIZE=1M _make_test_img -b "$BASE_NEW" -F $IMGFMT +TEST_IMG=$OVERLAY CLUSTER_SIZE=2M _make_test_img -b "$BASE_OLD" -F $IMGFMT + +echo +echo "Writing data to region [1MB, 3MB)" +echo + +$QEMU_IO "$BASE_OLD" -c "write -P 0xff 1M 2M" | _filter_qemu_io + +echo +echo "Rebasing" +echo + +$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 3M 1M" | _filter_qemu_io + +$QEMU_IMG map "$OVERLAY" | _filter_qemu_img_map + echo # success, all done diff --git a/tests/qemu-iotests/024.out b/tests/qemu-iotests/024.out index e1e8eea863463fe2c2e93ee998042bda8a29ad3a..8348148a31cc9445dbc9c4004a969dd3773ab225 100644 --- a/tests/qemu-iotests/024.out +++ b/tests/qemu-iotests/024.out @@ -244,4 +244,30 @@ Offset Length File 0 0x20000 TEST_DIR/subdir/t.IMGFMT 0x40000 0x20000 TEST_DIR/subdir/t.IMGFMT +=== Test that the region to copy does not exceed 2MB (IO_BUF_SIZE) === + +Creating backing chain + +Formatting 'TEST_DIR/subdir/t.IMGFMT.base_new', fmt=IMGFMT size=4194304 +Formatting 'TEST_DIR/subdir/t.IMGFMT.base_old', fmt=IMGFMT size=4194304 backing_file=TEST_DIR/subdir/t.IMGFMT.base_new backing_fmt=IMGFMT +Formatting 'TEST_DIR/subdir/t.IMGFMT', fmt=IMGFMT size=4194304 backing_file=TEST_DIR/subdir/t.IMGFMT.base_old backing_fmt=IMGFMT + +Writing data to region [1MB, 3MB) + +wrote 2097152/2097152 bytes at offset 1048576 +2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +Rebasing + +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) +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 + *** done