[Devel] [PATCH vz10 24/24] dm-ploop: fail BAT-writeback waiters instead of retrying forever on I/O error
Andrey Zhadchenko
andrey.zhadchenko at virtuozzo.com
Mon Jul 6 15:35:32 MSK 2026
NACK.
Same reasoning as for the [Devel] [PATCH vz10 23/24] dm-qcow2: fail
waiters instead of retrying forever after metadata I/O error
On 7/6/26 13:00, Konstantin Khorenko wrote:
> ploop_advance_local_after_bat_wb() unconditionally re-dispatched
> md->wait_llist (pios postponed by ploop_delay_if_md_busy() while this BAT
> page was already dirty/under writeback) for retry, regardless of whether the
> writeback that just completed succeeded or failed - the exact same class of
> bug just fixed for dm-qcow2 in commit db5b5d2d30d8 ("dm-qcow2: fail waiters
> instead of retrying forever after metadata I/O error"), found by auditing
> dm-ploop for the analogous pattern after that live repro.
>
> On a persistently failing backing device, a retried pio re-triggers the same
> BAT-page write, fails the same way, and lands back on md->wait_llist again -
> an unbounded retry storm that leaves the pio's originating I/O blocked in an
> uninterruptible wait forever (unkillable D state), wedging `ploop
> umount`/`dmsetup remove` and eventually `reboot` on the stuck task.
>
> A failed BAT writeback means the page's on-disk state was not persisted, so
> retrying it as if nothing happened is not safe. Thread the real bi_status
> through (instead of a plain success/failure bool) and fail md->wait_llist
> waiters with it via ploop_pio_endio() on failure, exactly like
> piwb->llready_data_pios (the data bios belonging to this same BAT update) are
> already correctly handled a few lines below. The success path is unchanged.
>
> Fixes: a9cd5e6dc646 ("dm-ploop: Add ploop target driver")
> Feature: dm-ploop: ploop target driver
> https://virtuozzo.atlassian.net/browse/VSTOR-137234
> Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
> ---
> drivers/md/dm-ploop-map.c | 28 ++++++++++++++++++++++++----
> 1 file changed, 24 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/md/dm-ploop-map.c b/drivers/md/dm-ploop-map.c
> index 48466435dd19..af6b95241564 100644
> --- a/drivers/md/dm-ploop-map.c
> +++ b/drivers/md/dm-ploop-map.c
> @@ -810,9 +810,10 @@ static void ploop_complete_cow(struct ploop_cow *cow, blk_status_t bi_status)
> */
> static void ploop_advance_local_after_bat_wb(struct ploop *ploop,
> struct ploop_index_wb *piwb,
> - bool success)
> + blk_status_t bi_status)
> {
> struct md_page *md = piwb->md;
> + bool success = !bi_status;
> u32 i, last, *bat_entries;
> map_index_t *dst_clu, off;
> unsigned long flags;
> @@ -890,7 +891,26 @@ static void ploop_advance_local_after_bat_wb(struct ploop *ploop,
> llist_for_each_safe(pos, t, wait_llist_pending) {
> pio = list_entry((struct list_head *)pos, typeof(*pio), list);
> INIT_LIST_HEAD(&pio->list);
> - list_add(&pio->list, &list);
> + /*
> + * These pios arrived while this BAT page's writeback
> + * was already in flight and were postponed
> + * (ploop_delay_if_md_busy()) to retry their own BAT
> + * update once it finished. If it failed, this page's
> + * on-disk state was not persisted, so retrying is not
> + * safe: on a persistently failing backing device the
> + * retried pio would immediately hit the same
> + * disk-level failure and land back on this list
> + * again - an unbounded retry storm that leaves the
> + * pio's (uninterruptible) originator blocked forever.
> + * Fail them, mirroring how piwb->llready_data_pios
> + * is already handled above.
> + */
> + if (success) {
> + list_add(&pio->list, &list);
> + } else {
> + pio->bi_status = bi_status;
> + ploop_pio_endio(pio);
> + }
> }
> }
>
> @@ -956,13 +976,13 @@ static void ploop_bat_write_finish(struct pio *pio, void *piwb_ptr,
> * a bio, subsequent read wants to see written data
> * (ploop_map() wants to see not zero bat_entries[.]).
> */
> - ploop_advance_local_after_bat_wb(ploop, piwb, true);
> + ploop_advance_local_after_bat_wb(ploop, piwb, bi_status);
> } else {
> /*
> * Index wb failed. Mark clusters as unallocated again.
> * piwb->count is zero, so all data writers compeleted.
> */
> - ploop_advance_local_after_bat_wb(ploop, piwb, false);
> + ploop_advance_local_after_bat_wb(ploop, piwb, bi_status);
> }
>
> spin_lock_irqsave(&piwb->lock, flags);
More information about the Devel
mailing list