* [PATCH hci-8.1 0/2] qcow2: fix discard-no-unref=on data corruption #VSTOR-151885
@ 2026-10-27 10:26 Andrey Drobyshev
2026-10-27 10:26 ` [PATCH hci-8.1 1/2] qcow2: fix snapshot data corruption with discard-no-unref=on #VSTOR-151885 Andrey Drobyshev
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Andrey Drobyshev @ 2026-10-27 10:26 UTC (permalink / raw)
To: svt-core; +Cc: andrey.drobyshev, den
Andrey Drobyshev (2):
qcow2: fix snapshot data corruption with discard-no-unref=on
#VSTOR-151885
iotests/290: add 'discard' and 'write -z -u' case with a snapshot
#VSTOR-151885
block/qcow2-cluster.c | 6 ++++--
tests/qemu-iotests/290 | 16 ++++++++++++++++
tests/qemu-iotests/290.out | 5 +++++
3 files changed, 25 insertions(+), 2 deletions(-)
--
2.47.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH hci-8.1 1/2] qcow2: fix snapshot data corruption with discard-no-unref=on #VSTOR-151885
2026-10-27 10:26 [PATCH hci-8.1 0/2] qcow2: fix discard-no-unref=on data corruption #VSTOR-151885 Andrey Drobyshev
@ 2026-10-27 10:26 ` Andrey Drobyshev
2026-10-27 10:28 ` no-reply
2026-10-27 10:26 ` [PATCH hci-8.1 2/2] iotests/290: add 'discard' and 'write -z -u' case with a snapshot #VSTOR-151885 Andrey Drobyshev
2026-10-27 11:04 ` [PATCH hci-8.1 0/2] qcow2: fix discard-no-unref=on data corruption #VSTOR-151885 Denis V. Lunev
2 siblings, 1 reply; 6+ messages in thread
From: Andrey Drobyshev @ 2026-10-27 10:26 UTC (permalink / raw)
To: svt-core; +Cc: andrey.drobyshev, den
Whenever option discard-no-unref=on is enabled, we bypass refcount
machinery and unconditionally punch hole in the data on 'discard' and
'write -z -u' paths. However, when this same cluster is also referenced
by an internal snapshot, such operations lead to problems. The active L2
table is copied before it is changed, so the snapshot metadata stays
correct, but the host range under it is punched out and the snapshot reads
zeroes there afterwards. qemu-img check finds nothing wrong.
Fix this by guarding the 'keep_reference' flag by the presence of the
QCOW_OFLAG_COPIED bit. I.e. only proceed with unconditional data
punching if we own this cluster exclusively.
Fixes: 42a2890a76f4 ("qcow2: add discard-no-unref option")
Signed-off-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
---
block/qcow2-cluster.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index dfe728cd8a5..c3b11272afd 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -2076,6 +2076,7 @@ discard_in_l2_slice(BlockDriverState *bs, uint64_t offset, uint64_t nb_clusters,
QCow2ClusterType cluster_type =
qcow2_get_cluster_type(bs, old_l2_entry);
bool keep_reference = (cluster_type != QCOW2_CLUSTER_COMPRESSED) &&
+ (old_l2_entry & QCOW_OFLAG_COPIED) &&
!full_discard &&
(s->discard_no_unref &&
type == QCOW2_DISCARD_REQUEST);
@@ -2312,8 +2313,9 @@ zero_in_l2_slice(BlockDriverState *bs, uint64_t offset,
QCow2ClusterType type = qcow2_get_cluster_type(bs, old_l2_entry);
bool unmap = (type == QCOW2_CLUSTER_COMPRESSED) ||
((flags & BDRV_REQ_MAY_UNMAP) && qcow2_cluster_is_allocated(type));
- bool keep_reference =
- (s->discard_no_unref && type != QCOW2_CLUSTER_COMPRESSED);
+ bool keep_reference = s->discard_no_unref &&
+ type != QCOW2_CLUSTER_COMPRESSED &&
+ (old_l2_entry & QCOW_OFLAG_COPIED);
uint64_t new_l2_entry = unmap ? 0 : old_l2_entry;
uint64_t new_l2_bitmap = old_l2_bitmap;
--
2.47.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH hci-8.1 2/2] iotests/290: add 'discard' and 'write -z -u' case with a snapshot #VSTOR-151885
2026-10-27 10:26 [PATCH hci-8.1 0/2] qcow2: fix discard-no-unref=on data corruption #VSTOR-151885 Andrey Drobyshev
2026-10-27 10:26 ` [PATCH hci-8.1 1/2] qcow2: fix snapshot data corruption with discard-no-unref=on #VSTOR-151885 Andrey Drobyshev
@ 2026-10-27 10:26 ` Andrey Drobyshev
2026-10-27 10:28 ` no-reply
2026-10-27 11:04 ` [PATCH hci-8.1 0/2] qcow2: fix discard-no-unref=on data corruption #VSTOR-151885 Denis V. Lunev
2 siblings, 1 reply; 6+ messages in thread
From: Andrey Drobyshev @ 2026-10-27 10:26 UTC (permalink / raw)
To: svt-core; +Cc: andrey.drobyshev, den
Before the previous commit, issuing 'discard' and 'write -z -u'
operations with discard-no-unref=on option enabled led to data
corruption. Add a test to cover this case.
Signed-off-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
---
tests/qemu-iotests/290 | 16 ++++++++++++++++
tests/qemu-iotests/290.out | 5 +++++
2 files changed, 21 insertions(+)
diff --git a/tests/qemu-iotests/290 b/tests/qemu-iotests/290
index 4eb929d15fa..9e711275867 100755
--- a/tests/qemu-iotests/290
+++ b/tests/qemu-iotests/290
@@ -126,6 +126,22 @@ $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
echo "# Output of qemu-img map for the image with kept reference"
$QEMU_IMG map --output=json "$NOUNREF_IMG" | _filter_qemu_img_map
+echo
+echo "### Discard with 'discard-no-unref' on a cluster shared with a snapshot"
+echo
+
+_make_test_img 128k
+$QEMU_IO -c 'write -q -P 0xaa 0 128k' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IMG snapshot -c snap "$TEST_IMG"
+QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT \
+$QEMU_IO -c 'discard -q 0 64k' -c 'write -q -z -u 64k 64k' --image-opts \
+ "driver=$IMGFMT,file.filename=$TEST_IMG,discard-no-unref=on" \
+ | _filter_qemu_io
+$QEMU_IO -c 'read -q -P 0 0 128k' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IMG snapshot -a snap "$TEST_IMG"
+$QEMU_IO -c 'read -q -P 0xaa 0 128k' "$TEST_IMG" | _filter_qemu_io
+_check_test_img
+
# success, all done
echo "*** done"
rm -f $seq.full
diff --git a/tests/qemu-iotests/290.out b/tests/qemu-iotests/290.out
index f790feae81a..aa5d164fa9f 100644
--- a/tests/qemu-iotests/290.out
+++ b/tests/qemu-iotests/290.out
@@ -86,4 +86,9 @@ Images are identical.
# Output of qemu-img map for the image with kept reference
[{ "start": 0, "length": 65536, "depth": 0, "present": true, "zero": false, "data": true, "compressed": false, "offset": OFFSET},
{ "start": 65536, "length": 65536, "depth": 0, "present": true, "zero": true, "data": false, "compressed": false, "offset": OFFSET}]
+
+### Discard with 'discard-no-unref' on a cluster shared with a snapshot
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072
+No errors were found on the image.
*** done
--
2.47.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH hci-8.1 2/2] iotests/290: add 'discard' and 'write -z -u' case with a snapshot #VSTOR-151885
2026-10-27 10:26 ` [PATCH hci-8.1 2/2] iotests/290: add 'discard' and 'write -z -u' case with a snapshot #VSTOR-151885 Andrey Drobyshev
@ 2026-10-27 10:28 ` no-reply
0 siblings, 0 replies; 6+ messages in thread
From: no-reply @ 2026-10-27 10:28 UTC (permalink / raw)
To: Andrey Drobyshev, svt-core; +Cc: den, andrey.drobyshev
> Before the previous commit, issuing 'discard' and 'write -z -u'
> operations with discard-no-unref=on option enabled led to data
> corruption. Add a test to cover this case.
>
> Signed-off-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261027102618.798471-1-andrey.drobyshev@virtuozzo.com?part=2
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH hci-8.1 1/2] qcow2: fix snapshot data corruption with discard-no-unref=on #VSTOR-151885
2026-10-27 10:26 ` [PATCH hci-8.1 1/2] qcow2: fix snapshot data corruption with discard-no-unref=on #VSTOR-151885 Andrey Drobyshev
@ 2026-10-27 10:28 ` no-reply
0 siblings, 0 replies; 6+ messages in thread
From: no-reply @ 2026-10-27 10:28 UTC (permalink / raw)
To: svt-core, Andrey Drobyshev; +Cc: den, andrey.drobyshev
> Whenever option discard-no-unref=on is enabled, we bypass refcount
> machinery and unconditionally punch hole in the data on 'discard' and
> 'write -z -u' paths. However, when this same cluster is also referenced
> by an internal snapshot, such operations lead to problems. The active L2
> table is copied before it is changed, so the snapshot metadata stays
> correct, but the host range under it is punched out and the snapshot reads
> zeroes there afterwards. qemu-img check finds nothing wrong.
>
> Fix this by guarding the 'keep_reference' flag by the presence of the
> QCOW_OFLAG_COPIED bit. I.e. only proceed with unconditional data
> punching if we own this cluster exclusively.
>
> Fixes: 42a2890a76f4 ("qcow2: add discard-no-unref option")
> Signed-off-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261027102618.798471-1-andrey.drobyshev@virtuozzo.com?part=1
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH hci-8.1 0/2] qcow2: fix discard-no-unref=on data corruption #VSTOR-151885
2026-10-27 10:26 [PATCH hci-8.1 0/2] qcow2: fix discard-no-unref=on data corruption #VSTOR-151885 Andrey Drobyshev
2026-10-27 10:26 ` [PATCH hci-8.1 1/2] qcow2: fix snapshot data corruption with discard-no-unref=on #VSTOR-151885 Andrey Drobyshev
2026-10-27 10:26 ` [PATCH hci-8.1 2/2] iotests/290: add 'discard' and 'write -z -u' case with a snapshot #VSTOR-151885 Andrey Drobyshev
@ 2026-10-27 11:04 ` Denis V. Lunev
2 siblings, 0 replies; 6+ messages in thread
From: Denis V. Lunev @ 2026-10-27 11:04 UTC (permalink / raw)
To: Andrey Drobyshev, svt-core; +Cc: den
On 10/27/26 11:26, Andrey Drobyshev wrote:
> Andrey Drobyshev (2):
> qcow2: fix snapshot data corruption with discard-no-unref=on
> #VSTOR-151885
> iotests/290: add 'discard' and 'write -z -u' case with a snapshot
> #VSTOR-151885
>
> block/qcow2-cluster.c | 6 ++++--
> tests/qemu-iotests/290 | 16 ++++++++++++++++
> tests/qemu-iotests/290.out | 5 +++++
> 3 files changed, 25 insertions(+), 2 deletions(-)
>
Reviewed-by: Denis V. Lunev <den@openvz.org>
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-27 11:05 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-27 10:26 [PATCH hci-8.1 0/2] qcow2: fix discard-no-unref=on data corruption #VSTOR-151885 Andrey Drobyshev
2026-10-27 10:26 ` [PATCH hci-8.1 1/2] qcow2: fix snapshot data corruption with discard-no-unref=on #VSTOR-151885 Andrey Drobyshev
2026-10-27 10:28 ` no-reply
2026-10-27 10:26 ` [PATCH hci-8.1 2/2] iotests/290: add 'discard' and 'write -z -u' case with a snapshot #VSTOR-151885 Andrey Drobyshev
2026-10-27 10:28 ` no-reply
2026-10-27 11:04 ` [PATCH hci-8.1 0/2] qcow2: fix discard-no-unref=on data corruption #VSTOR-151885 Denis V. Lunev
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.