From: Konstantin Khorenko <khorenko@virtuozzo.com>
To: Andrey Zhadchenko <andrey.zhadchenko@virtuozzo.com>
Cc: OpenVZ devel <devel@openvz.org>
Subject: Re: [Devel] [PATCH RHEL10 COMMIT] drivers/md/dm-qcow2: unmap cluster when discard clears last allocated subclusters
Date: Fri, 28 Aug 2026 19:03:50 +0200 [thread overview]
Message-ID: <202608281703.67SH3oRD1064013@f0.sw.ru> (raw)
In-Reply-To: <20260827160619.303398-9-andrey.zhadchenko@virtuozzo.com>
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 308a75e8320d7b50d8e445a288ed6d664ce5de10
Author: Andrey Zhadchenko <andrey.zhadchenko@virtuozzo.com>
Date: Thu Aug 27 19:06:16 2026 +0300
drivers/md/dm-qcow2: unmap cluster when discard clears last allocated subclusters
A subclusters discard only clears bits in the extended L2 bitmap and
keeps the cluster mapped. Teach dm-qcow2 to clear L2 entry if every
subcluster is discarded.
Feature: dm-qcow2: block device over QCOW2 files driver
https://virtuozzo.atlassian.net/browse/VSTOR-139406
Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko@virtuozzo.com>
Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Reviewed-by: Vasileios Almpanis <vasileios.almpanis@virtuozzo.com>
Reviewed-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
drivers/md/dm-qcow2-map.c | 26 +++++++++++++++++++++-----
1 file changed, 21 insertions(+), 5 deletions(-)
diff --git a/drivers/md/dm-qcow2-map.c b/drivers/md/dm-qcow2-map.c
index badd74e338de1..3154cae955916 100644
--- a/drivers/md/dm-qcow2-map.c
+++ b/drivers/md/dm-qcow2-map.c
@@ -122,6 +122,17 @@ static u32 qio_full_subclus_mask(struct qcow2 *qcow2, struct qio *qio)
return GENMASK(end_bit - 1, first_bit);
}
+static bool qio_discard_unmaps_cluster(struct qcow2 *qcow2, struct qio *qio,
+ struct qcow2_map *map)
+{
+ if (qio_covers_full_clu(qcow2, qio))
+ return true;
+ if (!qcow2->ext_l2 || map->compressed)
+ return false;
+ return (u32)map->ext_l2 &&
+ !((u32)map->ext_l2 & ~qio_full_subclus_mask(qcow2, qio));
+}
+
static loff_t compressed_clu_end_pos(loff_t start, sector_t compressed_sectors)
{
if (start % SECTOR_SIZE == 0)
@@ -2044,9 +2055,10 @@ static int parse_metadata(struct qcow2 *qcow2, struct qio **qio,
if (!write)
return 0;
- /* discards also need to update r1r2 */
+ /* cluster unmapping discards also need to update r1r2 */
if (!map->clu_is_cow &&
- !(op_is_discard((*qio)->bi_op) && qio_covers_full_clu(qcow2, *qio)))
+ !(op_is_discard((*qio)->bi_op) &&
+ qio_discard_unmaps_cluster(qcow2, *qio, map)))
return 0;
/* Now refcounters table/block */
@@ -3399,6 +3411,8 @@ static bool qio_discard_updates_metadata(struct qcow2 *qcow2, struct qio *qio,
* 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).
+ * Discarding last subclusters in a cluster clears it from L2 like a
+ * whole cluster discard.
* If the backing is present, set 'reads as zeroes' to avoid exposing
* stale data.
*/
@@ -3409,7 +3423,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;
+ bool whole_clu, unmap;
struct qio_ext *ext;
u64 new_ext_l2 = 0;
int ret;
@@ -3427,6 +3441,8 @@ static int prepare_cluster_discard(struct qcow2 *qcow2, struct qio **qio,
spin_unlock_irq(&qcow2->md_pages_lock);
whole_clu = qio_covers_full_clu(qcow2, *qio);
+ unmap = qio_discard_unmaps_cluster(qcow2, *qio, map);
+
if (whole_clu) {
if (zeroes && qcow2->ext_l2)
new_ext_l2 = (u64)U32_MAX << 32;
@@ -3438,7 +3454,7 @@ static int prepare_cluster_discard(struct qcow2 *qcow2, struct qio **qio,
new_ext_l2 |= mask << 32;
}
- if (whole_clu) {
+ if (unmap) {
if (map->clu_is_cow) {
/* Cluster is shared or compressed. Decrement refcount. */
unuse_pos = map->cow_clu_pos;
@@ -3463,7 +3479,7 @@ static int prepare_cluster_discard(struct qcow2 *qcow2, struct qio **qio,
ext->lx_md = md;
ext->new_ext_l2 = new_ext_l2;
- if (!whole_clu)
+ if (!unmap)
ext->only_set_ext_l2 = true;
else if (zeroes && !qcow2->ext_l2)
ext->set_all_zeroes = true;
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
next prev parent reply other threads:[~2026-08-28 17:05 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-27 16:06 [Devel] [PATCH VZ10 v4 00/11] dm-qcow2: improve discard and read-only merge handling Andrey Zhadchenko
2026-08-27 16:06 ` [Devel] [PATCH VZ10 v4 01/11] drivers/md/dm-qcow2: do not attach a bvec to discard qios Andrey Zhadchenko
2026-08-28 17:03 ` [Devel] [PATCH RHEL10 COMMIT] " Konstantin Khorenko
2026-08-27 16:06 ` [Devel] [PATCH VZ10 v4 02/11] drivers/md/dm-qcow2: fix revert_cluster_alloc() for ext_l2 case Andrey Zhadchenko
2026-08-28 17:03 ` [Devel] [PATCH RHEL10 COMMIT] " Konstantin Khorenko
2026-08-27 16:06 ` [Devel] [PATCH VZ10 v4 03/11] drivers/md/dm-qcow2: generalize COW index update machinery Andrey Zhadchenko
2026-08-28 17:03 ` [Devel] [PATCH RHEL10 COMMIT] " Konstantin Khorenko
2026-08-27 16:06 ` [Devel] [PATCH VZ10 v4 04/11] drivers/md/dm-qcow2: update metadata on whole cluster discard Andrey Zhadchenko
2026-08-28 17:03 ` [Devel] [PATCH RHEL10 COMMIT] " Konstantin Khorenko
2026-08-27 16:06 ` [Devel] [PATCH VZ10 v4 05/11] drivers/md/dm-qcow2: never trigger COW or allocation on discard Andrey Zhadchenko
2026-08-28 17:03 ` [Devel] [PATCH RHEL10 COMMIT] " Konstantin Khorenko
2026-08-27 16:06 ` [Devel] [PATCH VZ10 v4 06/11] drivers/md/dm-qcow2: set L2_READS_ALL_ZEROES after some discards Andrey Zhadchenko
2026-08-28 17:03 ` [Devel] [PATCH RHEL10 COMMIT] " Konstantin Khorenko
2026-08-27 16:06 ` [Devel] [PATCH VZ10 v4 07/11] drivers/md/dm-qcow2: update metadata on subclusters discard Andrey Zhadchenko
2026-08-28 17:03 ` [Devel] [PATCH RHEL10 COMMIT] " Konstantin Khorenko
2026-08-27 16:06 ` [Devel] [PATCH VZ10 v4 08/11] drivers/md/dm-qcow2: unmap cluster when discard clears last allocated subclusters Andrey Zhadchenko
2026-08-28 17:03 ` Konstantin Khorenko [this message]
2026-08-27 16:06 ` [Devel] [PATCH VZ10 v4 09/11] drivers/md/dm-qcow2: allow shared L1 entries during merge from RO image Andrey Zhadchenko
2026-08-28 17:03 ` [Devel] [PATCH RHEL10 COMMIT] " Konstantin Khorenko
2026-08-27 16:06 ` [Devel] [PATCH VZ10 v4 10/11] drivers/md/dm-qcow2: do discards during backward merge only for writable image Andrey Zhadchenko
2026-08-28 17:03 ` [Devel] [PATCH RHEL10 COMMIT] " Konstantin Khorenko
2026-08-27 16:06 ` [Devel] [PATCH VZ10 v4 11/11] drivers/md/dm-qcow2: respect zeroes during merge Andrey Zhadchenko
2026-08-28 17:03 ` [Devel] [PATCH RHEL10 COMMIT] " Konstantin Khorenko
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=202608281703.67SH3oRD1064013@f0.sw.ru \
--to=khorenko@virtuozzo.com \
--cc=andrey.zhadchenko@virtuozzo.com \
--cc=devel@openvz.org \
/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.