From 3ad6a0d2e3805867cd5af8ccea841acb3608de99 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 12 Jul 2018 15:00:08 +0200 Subject: [PATCH 214/268] block: Fix copy-on-read crash with partial final cluster RH-Author: Kevin Wolf Message-id: <20180712150008.23662-2-kwolf@redhat.com> Patchwork-id: 81331 O-Subject: [RHV-7.6 qemu-kvm-rhev PATCH 1/1] block: Fix copy-on-read crash with partial final cluster Bugzilla: 1590640 RH-Acked-by: Max Reitz RH-Acked-by: Fam Zheng RH-Acked-by: John Snow RH-Acked-by: Richard Jones If the virtual disk size isn't aligned to full clusters, bdrv_co_do_copy_on_readv() may get pnum == 0 before having the full cluster completed, which will let it run into an assertion failure: qemu-io: block/io.c:1203: bdrv_co_do_copy_on_readv: Assertion `skip_bytes < pnum' failed. Check for EOF, assert that we read at least as much as the read request originally wanted to have (which is true at EOF because otherwise bdrv_check_byte_request() would already have returned an error) and return success early even though we couldn't copy the full cluster. Signed-off-by: Kevin Wolf (cherry picked from commit b0ddcbbb36a66a605eb232b905cb49b1cc72e74e) Signed-off-by: Kevin Wolf Signed-off-by: Miroslav Rezanina --- block/io.c | 6 ++++++ tests/qemu-iotests/197 | 9 +++++++++ tests/qemu-iotests/197.out | 8 ++++++++ 3 files changed, 23 insertions(+) diff --git a/block/io.c b/block/io.c index ad8afc0..ac36d1c 100644 --- a/block/io.c +++ b/block/io.c @@ -1095,6 +1095,12 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child, pnum = MIN(cluster_bytes, max_transfer); } + /* Stop at EOF if the image ends in the middle of the cluster */ + if (ret == 0 && pnum == 0) { + assert(progress >= bytes); + break; + } + assert(skip_bytes < pnum); if (ret <= 0) { diff --git a/tests/qemu-iotests/197 b/tests/qemu-iotests/197 index 3ae4975..0369aa5 100755 --- a/tests/qemu-iotests/197 +++ b/tests/qemu-iotests/197 @@ -109,6 +109,15 @@ $QEMU_IO -f qcow2 -c map "$TEST_WRAP" _check_test_img $QEMU_IMG compare -f $IMGFMT -F qcow2 "$TEST_IMG" "$TEST_WRAP" +echo +echo '=== Partial final cluster ===' +echo + +_make_test_img 1024 +$QEMU_IO -f $IMGFMT -C -c 'read 0 1024' "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -f $IMGFMT -c map "$TEST_IMG" +_check_test_img + # success, all done echo '*** done' status=0 diff --git a/tests/qemu-iotests/197.out b/tests/qemu-iotests/197.out index 52b4137..8febda5 100644 --- a/tests/qemu-iotests/197.out +++ b/tests/qemu-iotests/197.out @@ -23,4 +23,12 @@ can't open device TEST_DIR/t.wrap.qcow2: Can't use copy-on-read on read-only dev 1023.938 MiB (0x3fff0000) bytes not allocated at offset 3 GiB (0xc0010000) No errors were found on the image. Images are identical. + +=== Partial final cluster === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1024 +read 1024/1024 bytes at offset 0 +1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +1 KiB (0x400) bytes allocated at offset 0 bytes (0x0) +No errors were found on the image. *** done -- 1.8.3.1