[Devel] [PATCH hci-8.1 v9 08/10] dm-qcow2: flag the image for check if reftable relocation fails late

no-reply at sashiko.virtuozzo.com no-reply at sashiko.virtuozzo.com
Wed Oct 28 18:17:34 MSK 2026


Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] dm-qcow2: relocate_refcount_table() late failure leaves target live on half-converted metadata
- [Low] dm-qcow2: relocate_refcount_table() logs the same message for two different failures
--

commit 6376ef1952337d69d9e96fb5403c763cf0015979
Author: Alexander Ivanov <alexander.ivanov at virtuozzo.com>

dm-qcow2: flag the image for check if reftable relocation fails late

This patch makes relocate_refcount_table() set md_writeback_error and log
a message when it fails after the header write that points to the new
reftable. With the flag set, wants_check reports the image and resume is
refused until the image is checked.

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

> 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

[ ... ]

> @@ -2351,6 +2351,8 @@ static int relocate_refcount_table(struct qcow2 *qcow2, struct qio **qio)
>  	if (ret) {
>  		/* Restore old R1 */
>  		set_reftable_in_raw_hdr(md0->page, old_pos, old_clus);
> +		QC_ERR(qcow2->tgt->ti, "failed to relocate refcount table");
> +		qcow2->tgt->md_writeback_error = true;
>  		goto err_free_r2_pages;
>  	}

[Severity: Low]
This isn't a bug, but the message logged here after a failed
qcow2_rw_page_sync() of the header is identical to the one logged at
err_hdr_written.

Can an administrator tell these two failures apart from the log?

In the header write failure case the cached header is restored and a clean
failure is possible, while at err_hdr_written the header has already been
written and the in-memory state is partly converted. Would distinct
messages make the two cases distinguishable?

Setting md_writeback_error here is conservative, since a short write may
still have reached disk, so that choice looks acceptable.

[ ... ]

> @@ -2405,12 +2407,16 @@ static int relocate_refcount_table(struct qcow2 *qcow2, struct qio **qio)
>  	for (i = old_pos; i < old_end; i += clu_size) {
>  		ret = qcow2_handle_r1r2_maps(qcow2, i, NULL, &r1, &r2, false);
>  		if (WARN_ON_ONCE(ret <= 0))
> -			return -EIO;
> +			goto err_hdr_written;
>  		mark_cluster_unused(qcow2, r2.md, r2.index_in_page, i);
>  	}
>  
>  	return 1;
>  
> +err_hdr_written:
> +	QC_ERR(qcow2->tgt->ti, "failed to relocate refcount table");
> +	qcow2->tgt->md_writeback_error = true;
> +	return -EIO;
>  err_free_r2_pages:

[Severity: Medium]
Does the target stay live on half-converted metadata after this path
returns -EIO?

By the time err_hdr_written is reached, hdr.refcount_table_offset and
hdr.refcount_table_clusters already point at the new reftable. Only some of
the R1 pages may have been renumbered, the new R2 may be only partly
connected, and the used/unused marking may be incomplete.

The only containment here is the md_writeback_error flag, and it is
consulted only in a few places:

dm-qcow2-target.c:qcow2_preresume()
    if (qcow2_wants_check(tgt)) {
        QC_ERR(ti, "image check and target reload are required");
        return -EIO;

Besides preresume, the flag is read only in the status dump, the
dirty-bit decision and the suspend-time truncate logic. dm-qcow2-map.c
only sets it and never reads it.

The allocation path does not check it either:

allocate_cluster()
    if (unlikely(pos == -ENOENT)) {
        ret = relocate_refcount_table(qcow2, &qio);
        if (ret <= 0)
            return ret;
        goto again;
    }

Can a later allocation that finds no free cluster re-enter
relocate_refcount_table() against the already modified hdr and cached
parameters? Can the target keep servicing writes and cause further
refcount inconsistency until suspend?

Would it make sense to make the target read-only, or to have
allocate_cluster() and the relocation entry check md_writeback_error? The
/* TODO: switch to RO */ comment is still present in the err_free_r2_pages
path of this function.

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



More information about the Devel mailing list