Blame SOURCES/kvm-block-Fix-copy-on-read-crash-with-partial-final-clus.patch

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