OpenVZ / Virtuozzo kernel development (devel@openvz.org)
 help / color / mirror / Atom feed
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 3/3] dm-qcow2: fix SEEK_HOLE/SEEK_DATA using an image freed by a merge
Date: Tue, 3 Nov 2026 08:47:20 +0000	[thread overview]
Message-ID: <010701a1a0976b7a-5cc63338-401c-47bc-a40a-a079c6ea49a3-000000@eu-central-1.amazonses.com> (raw)
In-Reply-To: <20261103083708.131379-4-den@openvz.org>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] dm-qcow2: qcow2_llseek_hole() holds inflight ref for whole walk, stalling ref switch
--

commit 042e70787bbad4a7f53038a208c72c6e24e2bfb5
Author: Denis V. Lunev <den@openvz.org>

dm-qcow2: fix SEEK_HOLE/SEEK_DATA using an image freed by a merge

This patch makes qcow2_llseek_hole() take an inflight reference with
qcow2_ref_inc() before it starts walking the image chain. It drops the
reference with qcow2_ref_dec() after the walk finishes. This is meant to
stop merge_backward complete from freeing an image while the walk is still
using it.

Link: https://virtuozzo.atlassian.net/browse/VSTOR-153050

> 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

[ ... ]

> @@ -4841,18 +4841,25 @@ static int qcow2_llseek_hole_qio(struct qio *qio, int whence, loff_t *result)
>  loff_t qcow2_llseek_hole(struct dm_target *ti, loff_t offset, int whence)
>  {
> -	struct qcow2 *qcow2 = to_qcow2_target(ti)->top;
> +	struct qcow2_target *tgt = to_qcow2_target(ti);
>  	loff_t result = -EINVAL;
> +	struct qcow2 *qcow2;
>  	struct qio *qio;
> +	u8 ref_index;
>  	int ret;
>  
> +	/* Keep merge_backward complete from freeing images under the walk */
> +	qcow2 = qcow2_ref_inc(tgt, &ref_index);
>  	qio = alloc_seek_qio(qcow2, NULL, qcow2->hdr.size);
> -	if (!qio)
> +	if (!qio) {
> +		qcow2_ref_dec(tgt, ref_index);
>  		return -ENOMEM;
> +	}
>  
>  	seek_qio_set_sector(qio, to_sector(offset));
>  
>  	ret = qcow2_llseek_hole_qio(qio, whence, &result);
> +	qcow2_ref_dec(tgt, ref_index);

[Severity: Medium]
This isn't a bug in the use-after-free fix itself, but the inflight ref
is now held across the whole qcow2_llseek_hole_qio() walk.  That walk is
unbounded for a large sparse image and sleeps in wait_for_completion()
while metadata pages are read.

Several callers of qcow2_inflight_ref_switch() have to drain that ref
first, so each of them now waits for the whole scan:

qcow2_merge_backward_complete()
  qcow2_inflight_ref_switch()
    wait_for_completion(comp)

This runs under ctl_mutex, so other control messages queue behind it.

set_backward_merge_in_process()
  top->pause_submitting_qios = true;
  qcow2_inflight_ref_switch()

While this waits, qcow2_submit_embedded_qio() parks new requests on
paused_qios. Can guest I/O to the target stall until the seek finishes?

qcow2_flush_deferred_activity()
  qcow2_inflight_ref_switch()

This is reached from suspend and teardown. dm_llseek_hole() checks
dm_suspended_md() only before the walk, so a suspend that starts
mid-walk would wait for the whole scan.

I did not find a deadlock. The seek's metadata reads call qcow2_ref_inc()
after the index flip and get the other slot, and the worker does not wait
on the ref. So the stall is bounded by the length of the walk.

Could the commit message mention this cost? Would it be reasonable to
drop and retake the ref per chunk and revalidate the top image, so
the ref is not held for the whole scan?

>  	/* In case of error remap ENXIO as it have special meaning for llseek */
>  	if (ret < 0)
>  		return (ret == -ENXIO) ? -EINVAL : ret;

-- 
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261103083708.131379-1-den@openvz.org?part=3

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

      reply	other threads:[~2026-11-03  8:48 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-03  8:37 [Devel] [PATCH hci-8.1 0/3] dm-qcow2: fix merges not stopping the users of the images they change Denis V. Lunev
2026-11-03  8:37 ` [Devel] [PATCH hci-8.1 1/3] dm-qcow2: fix a failed refcount table relocation leaking md pages Denis V. Lunev
2026-11-03  8:45   ` no-reply
2026-11-03  8:37 ` [Devel] [PATCH hci-8.1 2/3] dm-qcow2: fix backward merge of an inner image racing its reads Denis V. Lunev
2026-11-03  8:44   ` no-reply
2026-11-03  8:37 ` [Devel] [PATCH hci-8.1 3/3] dm-qcow2: fix SEEK_HOLE/SEEK_DATA using an image freed by a merge Denis V. Lunev
2026-11-03  8:47   ` no-reply [this message]

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=010701a1a0976b7a-5cc63338-401c-47bc-a40a-a079c6ea49a3-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