[Devel] [PATCH VZ10 10/10] drivers/md/dm-qcow2: respect zeroes during merge

Andrey Zhadchenko andrey.zhadchenko at virtuozzo.com
Wed Aug 12 21:56:38 MSK 2026


The merge machinery used to skip unallocated clusters, therefore
breaking all clusters with zero bits and non-zero backing.
Technically this bug was present even before discard changes, as
qcow2 image could have 'reads as zero' bits before being inserted
into dm-qcow2.
Properly commit all zero clusters (albeit with data for now).

https://virtuozzo.atlassian.net/browse/VSTOR-138288
Feature: dm-qcow2: block device over QCOW2 files driver
Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko at virtuozzo.com>
---
 drivers/md/dm-qcow2-map.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/md/dm-qcow2-map.c b/drivers/md/dm-qcow2-map.c
index 6f3b80a13e158..f73ba4d406cfd 100644
--- a/drivers/md/dm-qcow2-map.c
+++ b/drivers/md/dm-qcow2-map.c
@@ -2744,6 +2744,13 @@ static void requeue_if_ok(struct qcow2_target *tgt, struct qio *unused,
 	qcow2_dispatch_qios(qio->qcow2, qio, NULL);
 }
 
+static bool clu_zeroes_present(struct qcow2 *qcow2, struct qcow2_map *map)
+{
+	if (qcow2->ext_l2)
+		return (map->ext_l2 >> 32) != 0;
+	return map->all_zeroes;
+}
+
 static int prepare_backward_merge(struct qcow2 *qcow2, struct qio **qio,
 				  struct qcow2_map *map, bool write)
 {
@@ -2761,7 +2768,7 @@ static int prepare_backward_merge(struct qcow2 *qcow2, struct qio **qio,
 		}
 	}
 
-	if (!map->data_clu_alloced) {
+	if (!map->data_clu_alloced && !clu_zeroes_present(qcow2, map)) {
 		/* Strange COW at L1, except the merge from RO image */
 		WARN_ON_ONCE(map->clu_is_cow && qio_may_modify_image(qcow2, *qio));
 		if (fake_merge_qio(*qio)) {
@@ -2808,7 +2815,7 @@ static int prepare_backward_merge(struct qcow2 *qcow2, struct qio **qio,
 		goto endio;
 	}
 
-	if (!map->clu_is_cow) {
+	if (!map->clu_is_cow && map->data_clu_alloced) {
 		/* Forced set these to unuse them after discard */
 		(*qio)->ext->unuse_clu_pos = map->data_clu_pos;
 		(*qio)->ext->unuse_clu_end = map->data_clu_pos + qcow2->clu_size;
-- 
2.43.5



More information about the Devel mailing list