* [PATCH 0/3] qcow2: Fix alloc_cluster_abort() for pre-existing clusters
@ 2020-02-25 14:31 Max Reitz
2020-02-25 14:31 ` [PATCH 1/3] " Max Reitz
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Max Reitz @ 2020-02-25 14:31 UTC (permalink / raw)
To: qemu-block; +Cc: Kevin Wolf, qemu-stable, qemu-devel, Max Reitz
Hi,
With c3b6658c1a5a3fb2, Kevin has fixed a case in alloc_cluster_abort()
where we used to free a cluster that wasn’t even allocated by
handle_alloc(), thus leading to an error and/or corruption. Besides
external data files, there is another case where alloc_cluster_abort()
must not free the “new” cluster: Namely when the cluster isn’t new
because we’re reusing an existing pre-allocated zero cluster.
I think Berto’s subcluster series fixes this, too, but it’s still an
RFC, so I suppose we have to fix the bug independently of it.
Patch 2 adds a regression test; patch 3 adds a regression test for
Kevin’s patch c3b6658c1a5a3fb2 (which didn’t come with one).
Max Reitz (3):
qcow2: Fix alloc_cluster_abort() for pre-existing clusters
iotests/026: Test EIO on preallocated zero cluster
iotests/026: Test EIO on allocation in a data-file
block/qcow2-cluster.c | 2 +-
tests/qemu-iotests/026 | 53 ++++++++++++++++++++++++++++++
tests/qemu-iotests/026.out | 16 +++++++++
tests/qemu-iotests/026.out.nocache | 16 +++++++++
4 files changed, 86 insertions(+), 1 deletion(-)
--
2.24.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/3] qcow2: Fix alloc_cluster_abort() for pre-existing clusters
2020-02-25 14:31 [PATCH 0/3] qcow2: Fix alloc_cluster_abort() for pre-existing clusters Max Reitz
@ 2020-02-25 14:31 ` Max Reitz
2020-02-25 14:31 ` [PATCH 2/3] iotests/026: Test EIO on preallocated zero cluster Max Reitz
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Max Reitz @ 2020-02-25 14:31 UTC (permalink / raw)
To: qemu-block; +Cc: Kevin Wolf, qemu-stable, qemu-devel, Max Reitz
handle_alloc() reuses preallocated zero clusters. If anything goes
wrong during the data write, we do not change their L2 entry, so we
must not let qcow2_alloc_cluster_abort() free them.
Fixes: 8b24cd141549b5b264baeddd4e72902cfb5de23b
Cc: qemu-stable@nongnu.org
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
block/qcow2-cluster.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 78c95dfa16..17f1363279 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1026,7 +1026,7 @@ err:
void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m)
{
BDRVQcow2State *s = bs->opaque;
- if (!has_data_file(bs)) {
+ if (!has_data_file(bs) && !m->keep_old_clusters) {
qcow2_free_clusters(bs, m->alloc_offset,
m->nb_clusters << s->cluster_bits,
QCOW2_DISCARD_NEVER);
--
2.24.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/3] iotests/026: Test EIO on preallocated zero cluster
2020-02-25 14:31 [PATCH 0/3] qcow2: Fix alloc_cluster_abort() for pre-existing clusters Max Reitz
2020-02-25 14:31 ` [PATCH 1/3] " Max Reitz
@ 2020-02-25 14:31 ` Max Reitz
2020-02-25 14:31 ` [PATCH 3/3] iotests/026: Test EIO on allocation in a data-file Max Reitz
2020-02-26 13:53 ` [PATCH 0/3] qcow2: Fix alloc_cluster_abort() for pre-existing clusters Kevin Wolf
3 siblings, 0 replies; 5+ messages in thread
From: Max Reitz @ 2020-02-25 14:31 UTC (permalink / raw)
To: qemu-block; +Cc: Kevin Wolf, qemu-stable, qemu-devel, Max Reitz
Test what happens when writing data to a preallocated zero cluster, but
the data write fails.
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
tests/qemu-iotests/026 | 21 +++++++++++++++++++++
tests/qemu-iotests/026.out | 10 ++++++++++
tests/qemu-iotests/026.out.nocache | 10 ++++++++++
3 files changed, 41 insertions(+)
diff --git a/tests/qemu-iotests/026 b/tests/qemu-iotests/026
index a4aa74764f..0c1273c339 100755
--- a/tests/qemu-iotests/026
+++ b/tests/qemu-iotests/026
@@ -218,6 +218,27 @@ _make_test_img 64M
$QEMU_IO -c "write 0 1M" -c "write 0 1M" "$BLKDBG_TEST_IMG" | _filter_qemu_io
_check_test_img
+echo
+echo === Avoid freeing preallocated zero clusters on failure ===
+echo
+
+cat > "$TEST_DIR/blkdebug.conf" <<EOF
+[inject-error]
+event = "write_aio"
+errno = "5"
+once = "on"
+EOF
+
+_make_test_img $CLUSTER_SIZE
+# Create a preallocated zero cluster
+$QEMU_IO -c "write 0 $CLUSTER_SIZE" -c "write -z 0 $CLUSTER_SIZE" "$TEST_IMG" \
+ | _filter_qemu_io
+# Try to overwrite it (prompting an I/O error from blkdebug), thus
+# triggering the alloc abort code
+$QEMU_IO -c "write 0 $CLUSTER_SIZE" "$BLKDBG_TEST_IMG" | _filter_qemu_io
+
+_check_test_img
+
# success, all done
echo "*** done"
rm -f $seq.full
diff --git a/tests/qemu-iotests/026.out b/tests/qemu-iotests/026.out
index ff0817b6f2..83989996ff 100644
--- a/tests/qemu-iotests/026.out
+++ b/tests/qemu-iotests/026.out
@@ -643,4 +643,14 @@ write failed: Input/output error
wrote 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
No errors were found on the image.
+
+=== Avoid freeing preallocated zero clusters on failure ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1024
+wrote 1024/1024 bytes at offset 0
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 0
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+write failed: Input/output error
+No errors were found on the image.
*** done
diff --git a/tests/qemu-iotests/026.out.nocache b/tests/qemu-iotests/026.out.nocache
index 495d013007..9359d26d7e 100644
--- a/tests/qemu-iotests/026.out.nocache
+++ b/tests/qemu-iotests/026.out.nocache
@@ -651,4 +651,14 @@ write failed: Input/output error
wrote 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
No errors were found on the image.
+
+=== Avoid freeing preallocated zero clusters on failure ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1024
+wrote 1024/1024 bytes at offset 0
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 0
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+write failed: Input/output error
+No errors were found on the image.
*** done
--
2.24.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/3] iotests/026: Test EIO on allocation in a data-file
2020-02-25 14:31 [PATCH 0/3] qcow2: Fix alloc_cluster_abort() for pre-existing clusters Max Reitz
2020-02-25 14:31 ` [PATCH 1/3] " Max Reitz
2020-02-25 14:31 ` [PATCH 2/3] iotests/026: Test EIO on preallocated zero cluster Max Reitz
@ 2020-02-25 14:31 ` Max Reitz
2020-02-26 13:53 ` [PATCH 0/3] qcow2: Fix alloc_cluster_abort() for pre-existing clusters Kevin Wolf
3 siblings, 0 replies; 5+ messages in thread
From: Max Reitz @ 2020-02-25 14:31 UTC (permalink / raw)
To: qemu-block; +Cc: Kevin Wolf, qemu-stable, qemu-devel, Max Reitz
Test what happens when writing data to an external data file, where the
write requires an L2 entry to be allocated, but the data write fails.
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
tests/qemu-iotests/026 | 32 ++++++++++++++++++++++++++++++
tests/qemu-iotests/026.out | 6 ++++++
tests/qemu-iotests/026.out.nocache | 6 ++++++
3 files changed, 44 insertions(+)
diff --git a/tests/qemu-iotests/026 b/tests/qemu-iotests/026
index 0c1273c339..b05a4692cf 100755
--- a/tests/qemu-iotests/026
+++ b/tests/qemu-iotests/026
@@ -30,6 +30,7 @@ _cleanup()
{
_cleanup_test_img
rm "$TEST_DIR/blkdebug.conf"
+ rm -f "$TEST_IMG.data_file"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -239,6 +240,37 @@ $QEMU_IO -c "write 0 $CLUSTER_SIZE" "$BLKDBG_TEST_IMG" | _filter_qemu_io
_check_test_img
+echo
+echo === Avoid freeing external data clusters on failure ===
+echo
+
+# Similar test as the last one, except we test what happens when there
+# is an error when writing to an external data file instead of when
+# writing to a preallocated zero cluster
+_make_test_img -o "data_file=$TEST_IMG.data_file" $CLUSTER_SIZE
+
+# Put blkdebug above the data-file, and a raw node on top of that so
+# that blkdebug will see a write_aio event and emit an error
+$QEMU_IO -c "write 0 $CLUSTER_SIZE" \
+ "json:{
+ 'driver': 'qcow2',
+ 'file': { 'driver': 'file', 'filename': '$TEST_IMG' },
+ 'data-file': {
+ 'driver': 'raw',
+ 'file': {
+ 'driver': 'blkdebug',
+ 'config': '$TEST_DIR/blkdebug.conf',
+ 'image': {
+ 'driver': 'file',
+ 'filename': '$TEST_IMG.data_file'
+ }
+ }
+ }
+ }" \
+ | _filter_qemu_io
+
+_check_test_img
+
# success, all done
echo "*** done"
rm -f $seq.full
diff --git a/tests/qemu-iotests/026.out b/tests/qemu-iotests/026.out
index 83989996ff..c1b3b58482 100644
--- a/tests/qemu-iotests/026.out
+++ b/tests/qemu-iotests/026.out
@@ -653,4 +653,10 @@ wrote 1024/1024 bytes at offset 0
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
write failed: Input/output error
No errors were found on the image.
+
+=== Avoid freeing external data clusters on failure ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1024 data_file=TEST_DIR/t.IMGFMT.data_file
+write failed: Input/output error
+No errors were found on the image.
*** done
diff --git a/tests/qemu-iotests/026.out.nocache b/tests/qemu-iotests/026.out.nocache
index 9359d26d7e..8d5001648a 100644
--- a/tests/qemu-iotests/026.out.nocache
+++ b/tests/qemu-iotests/026.out.nocache
@@ -661,4 +661,10 @@ wrote 1024/1024 bytes at offset 0
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
write failed: Input/output error
No errors were found on the image.
+
+=== Avoid freeing external data clusters on failure ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1024 data_file=TEST_DIR/t.IMGFMT.data_file
+write failed: Input/output error
+No errors were found on the image.
*** done
--
2.24.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 0/3] qcow2: Fix alloc_cluster_abort() for pre-existing clusters
2020-02-25 14:31 [PATCH 0/3] qcow2: Fix alloc_cluster_abort() for pre-existing clusters Max Reitz
` (2 preceding siblings ...)
2020-02-25 14:31 ` [PATCH 3/3] iotests/026: Test EIO on allocation in a data-file Max Reitz
@ 2020-02-26 13:53 ` Kevin Wolf
3 siblings, 0 replies; 5+ messages in thread
From: Kevin Wolf @ 2020-02-26 13:53 UTC (permalink / raw)
To: Max Reitz; +Cc: qemu-devel, qemu-block, qemu-stable
Am 25.02.2020 um 15:31 hat Max Reitz geschrieben:
> With c3b6658c1a5a3fb2, Kevin has fixed a case in alloc_cluster_abort()
> where we used to free a cluster that wasn’t even allocated by
> handle_alloc(), thus leading to an error and/or corruption. Besides
> external data files, there is another case where alloc_cluster_abort()
> must not free the “new” cluster: Namely when the cluster isn’t new
> because we’re reusing an existing pre-allocated zero cluster.
>
> I think Berto’s subcluster series fixes this, too, but it’s still an
> RFC, so I suppose we have to fix the bug independently of it.
>
> Patch 2 adds a regression test; patch 3 adds a regression test for
> Kevin’s patch c3b6658c1a5a3fb2 (which didn’t come with one).
Thanks, applied to the block branch.
Kevin
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2020-02-26 13:54 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-02-25 14:31 [PATCH 0/3] qcow2: Fix alloc_cluster_abort() for pre-existing clusters Max Reitz
2020-02-25 14:31 ` [PATCH 1/3] " Max Reitz
2020-02-25 14:31 ` [PATCH 2/3] iotests/026: Test EIO on preallocated zero cluster Max Reitz
2020-02-25 14:31 ` [PATCH 3/3] iotests/026: Test EIO on allocation in a data-file Max Reitz
2020-02-26 13:53 ` [PATCH 0/3] qcow2: Fix alloc_cluster_abort() for pre-existing clusters Kevin Wolf
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.