* [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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).