From: no-reply@sashiko.virtuozzo.com
To: andrey.zhadchenko@virtuozzo.com, "Denis V. Lunev" <den@openvz.org>
Cc: devel@openvz.org
Subject: Re: [Devel] [PATCH hci-8.1 v2 1/3] dm-qcow2: fix a failed refcount table relocation leaking md pages
Date: Tue, 3 Nov 2026 09:13:41 +0000 [thread overview]
Message-ID: <010701a1a0af8baa-a0ca15fb-0759-4d53-a0b5-0db02a731ff8-000000@eu-central-1.amazonses.com> (raw)
In-Reply-To: <20261103090813.166986-2-den@openvz.org>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] dm-qcow2: err_free_r2_pages frees dirty md pages still on writeback lists
--
commit 774fe387096c63a6d4048c14687fd00ee87e6e1a
Author: Denis V. Lunev <den@openvz.org>
dm-qcow2: fix a failed refcount table relocation leaking md pages
This patch changes the error path of relocate_refcount_table() so that it
frees exactly the md pages the allocation loop inserted. Before, it freed
only one page per cluster starting from end. The patch tracks the range with
new_md_start and new_md_end and frees every page in that range.
Link: https://virtuozzo.atlassian.net/browse/VSTOR-153051
> diff --git a/drivers/md/dm-qcow2-map.c b/drivers/md/dm-qcow2-map.c
> --- a/drivers/md/dm-qcow2-map.c
> +++ b/drivers/md/dm-qcow2-map.c
[ ... ]
> @@ -2342,8 +2343,9 @@ static int relocate_refcount_table(struct qcow2 *qcow2, struct qio **qio)
> return ret;
>
> /* Alloc R1/R2 pages covering clusters of new R1 and new R2 */
> - for (i = pos + (u64)old_clus * clu_size; i < r2_end; i += PAGE_SIZE) {
> - ret = qcow2_alloc_and_insert_md_page(qcow2, i >> PAGE_SHIFT, &md);
> + new_md_start = pos + (u64)old_clus * clu_size;
> + for (new_md_end = new_md_start; new_md_end < r2_end; new_md_end += PAGE_SIZE) {
> + ret = qcow2_alloc_and_insert_md_page(qcow2, new_md_end >> PAGE_SHIFT, &md);
> if (ret < 0)
> goto err_free_r2_pages;
[ ... ]
> @@ -2419,7 +2421,7 @@ static int relocate_refcount_table(struct qcow2 *qcow2, struct qio **qio)
> return 1;
>
> err_free_r2_pages:
> - for (i = end; i < r2_end; i += clu_size) {
> + for (i = new_md_start; i < new_md_end; i += PAGE_SIZE) {
> ret = handle_md_page(qcow2, i >> PAGE_SHIFT, NULL, &md);
> if (ret <= 0)
> break;
> spin_lock_irq(&qcow2->md_pages_lock);
> qcow2_md_page_erase(qcow2, md);
> spin_unlock_irq(&qcow2->md_pages_lock);
> qcow2_free_md_page(md);
> }
[Severity: Medium]
Can this cleanup free md pages that are still linked on a writeback list?
The loop now erases and frees every page in [new_md_start, new_md_end).
It does not unlink md->wb_link, and it does not check MD_DIRTY or
MD_WRITEBACK.
Several gotos to err_free_r2_pages come after the header write, once pages
in this range may already be dirty:
- the renumber loop, when qcow2_md_page_renumber() returns NULL
(md_page_try_insert() failure, or error injection through
ALLOW_ERROR_INJECTION)
- the "Connect new R2 to new R1" loop, on calc_refcounters_map() or
handle_md_page() failure
- the mark_cluster_used() and mark_cluster_unused() loops, on
qcow2_handle_r1r2_maps() failure. This includes the non-WARN -EIO
from the "refblock=%llu, while no snapshots" sanity check.
By then qcow2_md_make_dirty() may have run on pages in the range:
qcow2_md_make_dirty() {
if (!(md->status & MD_DIRTY)) {
md->status |= MD_DIRTY;
list_add_tail(&md->wb_link, head);
...
mod_timer(&qcow2->slow_wb_timer, jiffies + WB_TIMEOUT_JI);
qcow2_md_page_erase() is only an rb_erase(). qcow2_free_md_page() is only
put_page() plus kfree(). Neither touches wb_link.
A freed struct md_page could then stay on wb_batch_list or
slow_wb_batch_list. A later writeback pass or slow_wb_timer would touch
freed memory.
The commit message says this is safe because "the gotos after it are
WARN_ON_ONCE() branches" that "want the image switched to read-only".
Is that accurate?
There is still no switch to read-only here, only the "TODO: switch to RO"
comment followed by return -EIO.
Some of the late branches are not WARN_ON_ONCE() branches. One example is
the -EIO from the "while no snapshots" check in qcow2_handle_r1r2_maps().
R2 pages could already be dirtied by mark_cluster_used() before this patch.
The R1 tail page and the additional pages of each R2 cluster are newly
exposed to this cleanup.
Would it make sense to unlink wb_link for dirty pages in this loop, or to
skip freeing the pages once the header write has succeeded?
--
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261103090813.166986-1-den@openvz.org?part=1
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
next prev parent reply other threads:[~2026-11-03 9:15 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-03 9:08 [Devel] [PATCH hci-8.1 v2 0/3] dm-qcow2: fix merges not stopping the users of the images they change Denis V. Lunev
2026-11-03 9:08 ` [Devel] [PATCH hci-8.1 v2 1/3] dm-qcow2: fix a failed refcount table relocation leaking md pages Denis V. Lunev
2026-11-03 9:13 ` no-reply [this message]
2026-11-03 9:27 ` Denis V. Lunev
2026-11-04 16:59 ` Konstantin Khorenko
2026-11-03 9:08 ` [Devel] [PATCH hci-8.1 v2 2/3] dm-qcow2: fix backward merge of an inner image racing its reads Denis V. Lunev
2026-11-03 9:13 ` no-reply
2026-11-04 16:59 ` Konstantin Khorenko
2026-11-03 9:08 ` [Devel] [PATCH hci-8.1 v2 3/3] dm-qcow2: fix SEEK_HOLE/SEEK_DATA using an image freed by a merge Denis V. Lunev
2026-11-03 9:15 ` no-reply
2026-11-04 16:59 ` Konstantin Khorenko
2026-11-04 13:15 ` [Devel] [PATCH hci-8.1 v2 0/3] dm-qcow2: fix merges not stopping the users of the images they change Andrey Zhadchenko
2026-11-04 16:59 ` 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=010701a1a0af8baa-a0ca15fb-0759-4d53-a0b5-0db02a731ff8-000000@eu-central-1.amazonses.com \
--to=no-reply@sashiko.virtuozzo.com \
--cc=andrey.zhadchenko@virtuozzo.com \
--cc=den@openvz.org \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox