From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.openvz.org (unknown [69.168.225.77]) by lore.virtuozzo.com (Postfix) with ESMTPS id E602D8013F for ; Fri, 28 Aug 2026 17:05:19 +0000 (UTC) Received: from mail.openvz.org (localhost [127.0.0.1]) by mail.openvz.org (8.14.4/8.14.4) with ESMTP id 67SH484T011583; Fri, 28 Aug 2026 20:04:08 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 67SH484T011583 Authentication-Results: mail.openvz.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=virtuozzo.com header.i=@virtuozzo.com header.b="IzGMpokl" Received: from mail-wr1-f70.google.com (mail-wr1-f70.google.com [209.85.221.70]) by mail.openvz.org (8.14.4/8.14.4) with ESMTP id 67SH3s0Q011522 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=FAIL) for ; Fri, 28 Aug 2026 20:03:54 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 67SH3s0Q011522 Received: by mail-wr1-f70.google.com with SMTP id ffacd0b85a97d-482bf4da3d5so682111f8f.1 for ; Fri, 28 Aug 2026 10:03:54 -0700 (PDT) X-Gm-Message-State: AFuF++k+1hHVbJuFIMh4Aizjl9ABMYOXhoacTfQuaUemgGnZ0zxjQu32 dspdGSVjB3lMkCi+oz6WkO1jy9Da+2zvRVBUF/qGDma9xGumTDXbFhmFYZv9q1Ekifxdpyf0SlV iO5Gs2IJbXYDauInGEpxmcxaDtLGjOSdR2ZiOSKk/LPnM+kBTBoeb3Q== X-Gm-Gg: AR+sD13b0t/OgzOZum6ZBBntgLQi1TZvCX10IQMx1u3RieKzr918GxY5kb2uFoYV9F8 K737e22FP93WPbENtc37QYgfoIfjPAZCqB5sunI/v4X7KWQNAMvLQvQjTmVNwLU0tDu+KfZ0ald BgcTPms3AxyTMm2IklYtgCiRdUiUdfApO8MvZMeiQPJyfoqrUxhl3fkVY9cpRMffwM6czBwuC0Y ZU7U8HucWqgXjcIMqrrsaFb5lOeuL8yKxVTSCyLtHVG7jbpbVKse/XDeo4ygi8AfMTprfgSdGC/ IGFGQu3ccbrHxDh9MDTckNuWbGwA5doUu9rxNHMa6/5qlhln/GCXX7AbeG2ScKOQBWSPyG2tJGk trFL2JtdRS1wjFoB6Jg== X-Received: by 2002:a05:6000:653:b0:482:eadd:174a with SMTP id ffacd0b85a97d-482f79c941cmr12623450f8f.17.1787936633884; Fri, 28 Aug 2026 10:03:53 -0700 (PDT) X-Received: by 2002:a05:6000:653:b0:482:eadd:174a with SMTP id ffacd0b85a97d-482f79c941cmr12623316f8f.17.1787936633264; Fri, 28 Aug 2026 10:03:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1787936633; cv=none; d=google.com; s=arc-20260327; b=PfpegE9mPecR01wXbbbAHBAZUpxAvF6IVkz0o3WSR3nj297FJaPtNjvAQP0WXKJ/f6 gKX4lchwkiZTrl4n5Zinf2c9Sc3j6hsWW7I+pfSvrglu0R2f1PbrBkKD+oam/WlUmgmT stUpzjPZKhrWXjGTXOXKVopvlxbNET1Zo4545jHJqWP8E8tbWysAeckBFBnwtMmWr4uY KUcaYyrbMP97l+NHAAm/C/NO2hB5CwlaqaWnY/hMyNRlF66VtT25ijttd0lSK1tsqz48 T0AxVYVHJP8OPhtHqmlRwHJq79iFNrB94ZyHwQvczwFVb08VLZWjiWwgTr8uTPUV01Da LHTw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=subject:in-reply-to:cc:to:from:message-id:date:dkim-signature; bh=lqn41FBHTAqKHuwGzRO4xQqbp9DhcEtbGNPesVyVPrM=; fh=Vum9jOrhj7HN5ByxRUgrKjNRrylYGqSqAPC0VlAu4Lc=; b=PjFkNdZ6cR5cP+CyFXb5acbDdq77/2ESh9i2x/6048M2LZ9Mq2RWiFk3DOoJGfeqtk kE3gWBQ5i6jYWGcR3j/Ul235WmNx0JMLuJY3Tkb7QRxeoY6R8svRnRsSzQibrWAawIx4 +Owt1oepl0RB0Fxeg5MwIatrmx5PVu4nHrGkHIAVf2tpY1HkKrNAEdN1CEBW9o9iHckS XlGBq+enrkRcTbyNIokmu2gcmGnoVGlO7hfoo3iCAZ8OGQLtCz6CE5Y4VfqUtmg1wzKx +RSPjui8g5obxwy5q5XLB102YbtlrxM76PO1z/an0KGx/uXM81SD20nhk3k9b+edJyrk dOBw==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@virtuozzo.com header.s=relay header.b=IzGMpokl; spf=pass (google.com: domain of khorenko@virtuozzo.com designates 130.117.225.111 as permitted sender) smtp.mailfrom=khorenko@virtuozzo.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=virtuozzo.com Received: from relay.virtuozzo.com (relay.virtuozzo.com. [130.117.225.111]) by mx.google.com with ESMTPS id ffacd0b85a97d-482fbb35f58si3595400f8f.281.2026.08.28.10.03.53 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 28 Aug 2026 10:03:53 -0700 (PDT) Received-SPF: pass (google.com: domain of khorenko@virtuozzo.com designates 130.117.225.111 as permitted sender) client-ip=130.117.225.111; Authentication-Results: mx.google.com; dkim=pass header.i=@virtuozzo.com header.s=relay header.b=IzGMpokl; spf=pass (google.com: domain of khorenko@virtuozzo.com designates 130.117.225.111 as permitted sender) smtp.mailfrom=khorenko@virtuozzo.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=virtuozzo.com DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuozzo.com; s=relay; h=Subject:From:Message-Id:Date:Content-Type: MIME-Version; bh=lqn41FBHTAqKHuwGzRO4xQqbp9DhcEtbGNPesVyVPrM=; b=IzGMpoklu4lZ QogQNCV2F/xHFyE7mENXfwmsRXpAhd53J071dc1qzoSJKmWAmQFrXRdfYu9yzC9abnGkyUD2P5izQ X1WcgeuV01t2w3yrI/5Nn20isKzu3wc+TLwZHfOJJq3kt+V1R7phQkgrN9R8sVctiqYWcA39EuCNu M9AK1KG/iO4uaDMOqMZtFnzbfRnlCgCdbzMiJA3dWdJt0pIq5VCPxcUJQELbiiK9gE75gIWKxpJuK HUKlairMBAMu7OEknKd8adpKqhPujAn30VhGu/Jv4FLI9363MXcouMFjxexGmp2+xI0MV9el06oB5 Ayd1kS5sBy6OGNitw38NyA==; Received: from ch-demo-asa.virtuozzo.com ([130.117.225.8] helo=f0.sw.ru) by relay.virtuozzo.com with esmtps (TLS1.3) tls TLS_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wzzxL-008du3-0a; Fri, 28 Aug 2026 19:03:49 +0200 Received: from f0.sw.ru (localhost [127.0.0.1]) by f0.sw.ru (8.18.1/8.18.1/Debian-2) with ESMTP id 67SH3qLt1064043; Fri, 28 Aug 2026 19:03:52 +0200 Received: (from kostja@localhost) by f0.sw.ru (8.18.1/8.18.1/Submit) id 67SH3pCj1064042; Fri, 28 Aug 2026 19:03:51 +0200 Date: Fri, 28 Aug 2026 19:03:51 +0200 Message-Id: <202608281703.67SH3pCj1064042@f0.sw.ru> X-Authentication-Warning: f0.sw.ru: kostja set sender to khorenko@virtuozzo.com using -f From: Konstantin Khorenko To: Andrey Zhadchenko In-Reply-to: <20260827160619.303398-8-andrey.zhadchenko@virtuozzo.com> X-OZ-Fwd: true Cc: OpenVZ devel Subject: Re: [Devel] [PATCH RHEL10 COMMIT] drivers/md/dm-qcow2: update metadata on subclusters discard X-BeenThere: devel@openvz.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: OpenVZ development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: devel-bounces@openvz.org Errors-To: devel-bounces@openvz.org The commit is pushed to "branch-rh10-6.12.0-211.39.1.16.x.vz10-ovz" and will appear at git@bitbucket.org:openvz/vzkernel.git after rh10-6.12.0-211.39.1.16.11.vz10 ------> commit a119a1f9e812f88c705c1ce8624e18abb5b7a727 Author: Andrey Zhadchenko Date: Thu Aug 27 19:06:15 2026 +0300 drivers/md/dm-qcow2: update metadata on subclusters discard On images with extended L2 entries a discard smaller than the whole cluster only punches a hole in the image file, while the subcluster allocation bitmap still reports the range as allocated. Extend prepare_cluster_discard() to also handle discards covering whole subclusters of a mapped non-compressed cluster: clear the "allocated" bits of the covered subclusters in the extended L2 entry via the existing only_set_ext_l2 machinery. If the range may be mapped in lower delta, set the "reads as zeroes" bits instead, so the discarded range doesn't expose stale lower data. The cluster itself remains allocated, so refcounts are not touched and the unuse stage has nothing to do (empty unuse range). The covered range is hole punched unless the cluster is shared with a snapshot. ext_l2 and unuse range handling are in different if blocks for a while: next patch will cover the case when we need uncoupling. Feature: dm-qcow2: block device over QCOW2 files driver https://virtuozzo.atlassian.net/browse/VSTOR-139406 Signed-off-by: Andrey Zhadchenko Reviewed-by: Pavel Tikhomirov Reviewed-by: Vasileios Almpanis Reviewed-by: Konstantin Khorenko --- drivers/md/dm-qcow2-map.c | 69 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 11 deletions(-) diff --git a/drivers/md/dm-qcow2-map.c b/drivers/md/dm-qcow2-map.c index 0a164c6f56c2d..badd74e338de1 100644 --- a/drivers/md/dm-qcow2-map.c +++ b/drivers/md/dm-qcow2-map.c @@ -107,6 +107,21 @@ static bool qio_covers_full_clu(struct qcow2 *qcow2, struct qio *qio) qio->bi_iter.bi_size == qcow2->clu_size; } +/* Mask of subclusters fully covered by qio (qio is trimmed inward) */ +static u32 qio_full_subclus_mask(struct qcow2 *qcow2, struct qio *qio) +{ + u32 off = bytes_off_in_cluster(qcow2, qio); + u32 first_bit = DIV_ROUND_UP(off, qcow2->subclu_size); + u32 end_bit = (off + qio->bi_iter.bi_size) / qcow2->subclu_size; + + WARN_ON_ONCE(!qcow2->ext_l2); + + if (end_bit <= first_bit) + return 0; + + return GENMASK(end_bit - 1, first_bit); +} + static loff_t compressed_clu_end_pos(loff_t start, sector_t compressed_sectors) { if (start % SECTOR_SIZE == 0) @@ -3357,11 +3372,21 @@ static void issue_discard(struct qcow2_map *map, struct qio *qio) static bool qio_discard_updates_metadata(struct qcow2 *qcow2, struct qio *qio, struct qcow2_map *map) { + u32 mask; + if (!(map->level & L2_LEVEL) || !map->data_clu_alloced) return false; if (qio_covers_full_clu(qcow2, qio)) return true; - return false; + if (!qcow2->ext_l2 || map->compressed) + return false; + + mask = qio_full_subclus_mask(qcow2, qio); + if ((u32)map->ext_l2 & mask) + return true; + + return maybe_mapped_in_lower_delta(qcow2, qio) && + (mask & ~(u32)(map->ext_l2 >> 32)); } /* @@ -3371,6 +3396,9 @@ static bool qio_discard_updates_metadata(struct qcow2 *qcow2, struct qio *qio, * * Discard covering the whole cluster replaces the entry and unuses * the discarded (or COW source) cluster. + * Subclusters fully covered by the discard are marked unallocated in + * ext_l2 bitmap: the cluster itself remains allocated, so refcounts + * are not touched (hence empty unuse range). * If the backing is present, set 'reads as zeroes' to avoid exposing * stale data. */ @@ -3381,6 +3409,7 @@ static int prepare_cluster_discard(struct qcow2 *qcow2, struct qio **qio, u32 index_in_page = map->l2.index_in_page; struct md_page *md = map->l2.md; loff_t unuse_pos, unuse_end; + bool whole_clu; struct qio_ext *ext; u64 new_ext_l2 = 0; int ret; @@ -3397,17 +3426,33 @@ static int prepare_cluster_discard(struct qcow2 *qcow2, struct qio **qio, } spin_unlock_irq(&qcow2->md_pages_lock); - if (map->clu_is_cow) { - /* Cluster is shared or compressed. Decrement refcount. */ - unuse_pos = map->cow_clu_pos; - unuse_end = map->cow_clu_end; + whole_clu = qio_covers_full_clu(qcow2, *qio); + if (whole_clu) { + if (zeroes && qcow2->ext_l2) + new_ext_l2 = (u64)U32_MAX << 32; + } else { + u64 mask = qio_full_subclus_mask(qcow2, *qio); + + new_ext_l2 = map->ext_l2 & ~(mask << 32 | mask); + if (zeroes) + new_ext_l2 |= mask << 32; + } + + if (whole_clu) { + if (map->clu_is_cow) { + /* Cluster is shared or compressed. Decrement refcount. */ + unuse_pos = map->cow_clu_pos; + unuse_end = map->cow_clu_end; + } else { + /* Nobody else refers the cluster: unuse it */ + unuse_pos = map->data_clu_pos; + unuse_end = map->data_clu_pos + qcow2->clu_size; + } } else { - /* Nobody else refers the cluster: unuse it after discard */ - unuse_pos = map->data_clu_pos; - unuse_end = map->data_clu_pos + qcow2->clu_size; + /* Subclusters become unallocated, cluster remains */ + unuse_pos = 0; + unuse_end = 0; } - if (zeroes && qcow2->ext_l2) - new_ext_l2 = (u64)U32_MAX << 32; ret = prepare_l_entry_replace(qcow2, map, *qio, md, index_in_page, unuse_pos, unuse_end, L2_LEVEL); @@ -3418,7 +3463,9 @@ static int prepare_cluster_discard(struct qcow2 *qcow2, struct qio **qio, ext->lx_md = md; ext->new_ext_l2 = new_ext_l2; - if (zeroes && !qcow2->ext_l2) + if (!whole_clu) + ext->only_set_ext_l2 = true; + else if (zeroes && !qcow2->ext_l2) ext->set_all_zeroes = true; (*qio)->flags |= QIO_IS_DISCARD_FL; _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel