From: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
To: svt-core@virtuozzo.com
Cc: andrey.drobyshev@virtuozzo.com, den@openvz.org
Subject: [PATCH hci-8.1 1/2] qcow2: fix snapshot data corruption with discard-no-unref=on #VSTOR-151885
Date: Tue, 27 Oct 2026 12:26:17 +0200 [thread overview]
Message-ID: <20261027102618.798471-2-andrey.drobyshev@virtuozzo.com> (raw)
In-Reply-To: <20261027102618.798471-1-andrey.drobyshev@virtuozzo.com>
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
next prev parent reply other threads:[~2026-10-27 10:26 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
2026-10-27 10:28 ` [PATCH hci-8.1 1/2] qcow2: fix snapshot data corruption with discard-no-unref=on #VSTOR-151885 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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261027102618.798471-2-andrey.drobyshev@virtuozzo.com \
--to=andrey.drobyshev@virtuozzo.com \
--cc=den@openvz.org \
--cc=svt-core@virtuozzo.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.