OpenVZ / Virtuozzo kernel development (devel@openvz.org)
 help / color / mirror / Atom feed
From: no-reply@sashiko.virtuozzo.com
To: den@openvz.org, Alexander Ivanov <alexander.ivanov@virtuozzo.com>
Cc: devel@openvz.org
Subject: Re: [Devel] [PATCH hci-8.1 v6 11/12] dm-ploop: reload metadata on resume
Date: Tue, 13 Oct 2026 11:35:51 +0000	[thread overview]
Message-ID: <010701a1350c284d-137ccce0-774e-492c-ab3b-2a320c743e99-000000@eu-central-1.amazonses.com> (raw)
In-Reply-To: <20261013111604.142989-12-alexander.ivanov@virtuozzo.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] dm-ploop: postsuspend waits unkillably on inflight_md even in standby
- [Medium] dm-ploop: killed wait in postsuspend() leaves prealloc pending after device is marked suspended
--

commit 881f9bc269db1bbaa88bf766f12f3d91d98c7d92
Author: Alexander Ivanov <alexander.ivanov@virtuozzo.com>

dm-ploop: reload metadata on resume

This patch reloads the top delta header, the BAT of every delta and the
delta file sizes in ploop_preresume(), and rebuilds the BAT tree and
holes_bitmap. It also moves preallocation to after the reload and makes
postsuspend wait for pending preallocation and for inflight_md. Standby
state is now tracked per ploop instead of through the queue bit.

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

> diff --git a/drivers/md/dm-ploop-map.c b/drivers/md/dm-ploop-map.c
> --- a/drivers/md/dm-ploop-map.c
> +++ b/drivers/md/dm-ploop-map.c

[ ... ]

> @@ -1259,6 +1259,12 @@ static int ploop_no_pending_prealloc(struct ploop *ploop)
>  	return ret;
>  }
>  
> +void ploop_wait_prealloc(struct ploop *ploop)
> +{
> +	wait_event_killable(ploop->dispatcher_wq_prealloc,
> +			    ploop_no_pending_prealloc(ploop));
> +}
> +

[Severity: Medium]
The return value of wait_event_killable() is discarded here, so a killed
wait looks the same as a completed one to the caller.

Can this leave a prealloc pending after the device is marked suspended?

Suppose the dmsetup task gets a fatal signal while ploop_postsuspend() is
in ploop_wait_prealloc(), and prealloc_size or prealloc_in_progress is
still non-zero. Then:

ploop_postsuspend()
    ploop_wait_prealloc()          /* returns -ERESTARTSYS, ignored */
    wait_event(ploop->inflight_md_wq, ...);
    ploop_set_suspended(ti, true);

The postsuspend callback returns void, so dm_suspend() cannot abort. The
old allocator thread keeps running and can still extend or truncate the top
delta.

The new ploop's ploop_preresume() checks only its own prealloc state, which
is zero:

ploop_preresume()
    } else if (!ploop_is_standby(ploop) &&
               ploop_no_pending_prealloc(ploop)) {
        reload = true;
        ...
        ret = ploop_reload_metadata(ploop);

It therefore reloads and caches a file size that the old allocator is still
changing. Can the old allocator's later truncate then cut off clusters that
the new ploop has already written?

The new comment in ploop_postsuspend() says "a ploop of a reloaded table may
see a stale size, and a late truncate of our allocator may shrink the file
under it", but nothing in the code prevents that outcome. Is there a way to
detect the killed wait, for example by checking the return value and
refusing to proceed?

> diff --git a/drivers/md/dm-ploop-target.c b/drivers/md/dm-ploop-target.c
> --- a/drivers/md/dm-ploop-target.c
> +++ b/drivers/md/dm-ploop-target.c

[ ... ]

>  static void ploop_postsuspend(struct dm_target *ti)
>  {
> +	struct ploop *ploop = ti->private;
> +
> +	/*
> +	 * Let the next resumed ploop (maybe of reloaded table)
> +	 * see final size of the top delta. Don't wait in standby
> +	 * mode: the allocator may be stuck on the dead file, while
> +	 * dm_replace() of libploop must be able to suspend the device
> +	 * to recover it. The wait is killable for the same reason.
> +	 * If the wait is skipped or killed, a ploop of a reloaded
> +	 * table may see a stale size, and a late truncate of our
> +	 * allocator may shrink the file under it.
> +	 */
> +	if (!ploop_is_standby(ploop))
> +		ploop_wait_prealloc(ploop);
> +	/*
> +	 * Data bios are completed before BAT writeback is finished
> +	 * (see ploop_put_piwb()), so wait for it explicitly to make
> +	 * md pages clean for ploop_reload_metadata().
> +	 */
> +	wait_event(ploop->inflight_md_wq, !atomic_read(&ploop->inflight_md));

[Severity: Medium]
The prealloc wait above is skipped in standby and is killable, because the
comment says the allocator may be stuck on a dead file. The inflight_md
wait here is neither.

Can this wait_event() hang suspend in uninterruptible sleep on a failing
device?

inflight_md only drops when the BAT write pio completes:

ploop_index_wb_submit()
    ploop_runners_add_work(ploop, pio);   /* file IO on the top delta */
...
ploop_put_piwb()
    ploop_dec_inflight_md()
        if (atomic_dec_and_test(&ploop->inflight_md))
            wake_up_locked(&ploop->inflight_md_wq);

If the device is in standby because of a hung backing file and a BAT write
is in flight on that same file, inflight_md never reaches zero.
ploop_presuspend() only waits for kt_worker->inflight_pios, so it does not
drain this.

Before this patch postsuspend never waited on inflight_md, so dm_replace()
could suspend such a device. Should this wait also be skipped in standby
and made killable, like ploop_wait_prealloc()?

A follow-up patch in the series, 'dm-ploop: truncate unused tail of top
delta on suspend', keeps this wait_event() unchanged and moves the call
under ctl_rwsem, so a hang there would hold ctl_rwsem for write while
waiting.

-- 
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261013111604.142989-1-alexander.ivanov@virtuozzo.com?part=11

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

  reply	other threads:[~2026-10-13 11:37 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-13 11:15 [Devel] [PATCH hci-8.1 v6 00/12] dm-ploop: give back unused tail of top delta on suspend Alexander Ivanov
2026-10-13 11:15 ` [Devel] [PATCH hci-8.1 v6 01/12] dm-ploop: fix u32 overflow of the delta BAT byte size Alexander Ivanov
2026-10-13 11:23   ` no-reply
2026-10-13 11:15 ` [Devel] [PATCH hci-8.1 v6 02/12] dm-ploop: fix lost wakeup in ploop_allocator() Alexander Ivanov
2026-10-13 11:21   ` no-reply
2026-10-13 11:15 ` [Devel] [PATCH hci-8.1 v6 03/12] dm-ploop: reject a delta header whose BAT does not cover the target Alexander Ivanov
2026-10-13 11:22   ` no-reply
2026-10-13 11:15 ` [Devel] [PATCH hci-8.1 v6 04/12] dm-ploop: reject empty deltas Alexander Ivanov
2026-10-13 11:24   ` no-reply
2026-10-13 11:15 ` [Devel] [PATCH hci-8.1 v6 05/12] dm-ploop: set delta is_raw before applying its mappings Alexander Ivanov
2026-10-13 11:24   ` no-reply
2026-10-13 11:15 ` [Devel] [PATCH hci-8.1 v6 06/12] dm-ploop: factor out ploop_read_delta() from ploop_add_delta() Alexander Ivanov
2026-10-13 11:25   ` no-reply
2026-10-13 11:15 ` [Devel] [PATCH hci-8.1 v6 07/12] dm-ploop: take bat_lock around md page lookup in ploop_llseek_hole() Alexander Ivanov
2026-10-13 11:26   ` no-reply
2026-10-13 11:16 ` [Devel] [PATCH hci-8.1 v6 08/12] dm-ploop: use wake_up() for inflight_md_wq and dispatcher_wq_prealloc Alexander Ivanov
2026-10-13 11:26   ` no-reply
2026-10-13 11:16 ` [Devel] [PATCH hci-8.1 v6 09/12] dm-ploop: fix use-after-free on the last inflight_md decrement Alexander Ivanov
2026-10-13 11:30   ` no-reply
2026-10-13 11:16 ` [Devel] [PATCH hci-8.1 v6 10/12] dm-ploop: fix flip_upper_deltas racing with resume Alexander Ivanov
2026-10-13 11:28   ` no-reply
2026-10-13 11:16 ` [Devel] [PATCH hci-8.1 v6 11/12] dm-ploop: reload metadata on resume Alexander Ivanov
2026-10-13 11:35   ` no-reply [this message]
2026-10-13 12:46     ` Alexander Ivanov
2026-10-13 11:16 ` [Devel] [PATCH hci-8.1 v6 12/12] dm-ploop: truncate unused tail of top delta on suspend Alexander Ivanov
2026-10-13 11:38   ` no-reply
2026-10-13 12:53     ` Alexander Ivanov

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=010701a1350c284d-137ccce0-774e-492c-ab3b-2a320c743e99-000000@eu-central-1.amazonses.com \
    --to=no-reply@sashiko.virtuozzo.com \
    --cc=alexander.ivanov@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