[Devel] [PATCH hci-8.1 v11 08/10] dm-qcow2: leak clusters allocated for a failed L1/L2 writeback

no-reply at sashiko.virtuozzo.com no-reply at sashiko.virtuozzo.com
Mon Nov 9 17:14:21 MSK 2026


Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] dm-qcow2: clusters leaked on failed L1/L2 writeback; L1 alloc retry repeats leak
--

Subject: Re: [PATCH] dm-qcow2: leak clusters allocated for a failed L1/L2 writeback

commit 8f9e1298a69365ad6d96d693fc232f0ee7761431
Author: Alexander Ivanov <alexander.ivanov at virtuozzo.com>

dm-qcow2: leak clusters allocated for a failed L1/L2 writeback

This commit stops dropping the refcount of clusters allocated for a failed
L1/L2 writeback. revert_l_entries_update() now only restores the in-memory
entries, and complete_wbd() clears FREE_ALLOCATED_CLU on the qios ended
with the error.

> 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

[ ... ]

>  static void revert_l_entries_update(struct qcow2 *qcow2, struct wb_desc *wbd)
>  {
> +	struct page *pe_page = wbd->pe_page;
> +	u64 old;
> +	int i;
>  
>  	lockdep_assert_held(&qcow2->md_pages_lock);
>  	for_each_set_bit(i, wbd->changed_indexes, LX_INDEXES_PER_PAGE) {
>  		/* Here we restore prealloced and compressed clu mappings */
> +		old = pe_page ? get_u64_from_be_page(pe_page, i) : 0;
> +		set_u64_to_be_page(wbd->md->page, i, old);
>  	}
>  }

[ ... ]

> @@ -1408,6 +1373,7 @@ static void complete_wbd(struct qcow2 *qcow2, struct wb_desc *wbd)
>  		LIST_HEAD(wait_list);
>  		LIST_HEAD(end_list);
>  		unsigned long flags;
> +		struct qio *qio;
>  
>  		spin_lock_irqsave(&qcow2->md_pages_lock, flags);
>  		revert_l_entries_update(qcow2, wbd);
> @@ -1415,6 +1381,8 @@ static void complete_wbd(struct qcow2 *qcow2, struct wb_desc *wbd)
>  				       &wait_list, &end_list);
>  		spin_unlock_irqrestore(&qcow2->md_pages_lock, flags);
>  
> +		list_for_each_entry(qio, &end_list, link)
> +			qio->ext->cleanup_mask &= ~FREE_ALLOCATED_CLU;
>  		qcow2_dispatch_qios(qcow2, NULL, &wait_list);
>  		end_qios(&end_list, errno_to_blk_status(wbd->ret));

[Severity: Medium]
Can this leak more than one cluster per failed writeback in the L1 case?

In prepare_l1l2_allocation(), the qio that allocated an L2-table cluster is
queued on the L1 page wait list, not on wbd->dependent_list:

    list_add_tail(&qio->link, &map->l1.md->wait_list);

On a failed writeback, complete_wbd() calls clear_writeback_status(), which
does:

    list_splice_init(&md->wait_list, wait_list);
    ...
    list_splice_init(&md->wbd->dependent_list, end_list);

Only dependent_list is ended with the error. The qios on md->wait_list are
re-dispatched through qcow2_dispatch_qios().

revert_l_entries_update() has already reset the L1 entry to 0, so the
re-dispatched qio finds it empty and allocates another L2-table cluster,
dirties L1 and attempts writeback again. The cluster from the earlier attempt
is no longer freed, since mark_cluster_unused() is gone.

With a persistent L1 writeback error, does each retry cycle leak one more
cluster? Before this patch the cluster was freed, so the retry reused the
same one.

The L2 data-cluster and COW cases look bounded, since those qios sit on
dependent_list and end with the error, losing one cluster per failed request.

I did not find anything later in the series that reclaims the leaked
clusters. Nothing appears to roll back free_cluster_search_pos either.

The commit message says:

> So the image needs no check and resume needs no refusal.

Is this accurate? The leaked case is exactly the one that check repairs,
and the message does not mention that a repeated L1 allocation retry can
leak further clusters.

-- 
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261109140143.1408038-2-alexander.ivanov@virtuozzo.com?part=8



More information about the Devel mailing list