block/mirror: fix assertion failure upon duplicate complete for job using 'replaces'

If s->replace_blocker was already set by an earlier invocation of
mirror_complete(), then there will be an assertion failure when
error_setg() is called for it a second time. The bdrv_op_block_all()
and bdrv_ref() operations should only be done a single time too.

Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
Message-Id: <20260311145717.668492-2-f.ebner@proxmox.com>
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
This commit is contained in:
Fiona Ebner
2026-03-11 15:54:25 +01:00
committed by Hanna Czenczek
parent 9c8430f5d6
commit 9ac85f4cc7

View File

@@ -1276,23 +1276,25 @@ static void mirror_complete(Job *job, Error **errp)
return;
}
/* block all operations on to_replace bs */
if (s->replaces) {
s->to_replace = bdrv_find_node(s->replaces);
if (!s->to_replace) {
error_setg(errp, "Node name '%s' not found", s->replaces);
return;
if (!s->should_complete) {
/* block all operations on to_replace bs */
if (s->replaces) {
s->to_replace = bdrv_find_node(s->replaces);
if (!s->to_replace) {
error_setg(errp, "Node name '%s' not found", s->replaces);
return;
}
/* TODO Translate this into child freeze system. */
error_setg(&s->replace_blocker,
"block device is in use by block-job-complete");
bdrv_op_block_all(s->to_replace, s->replace_blocker);
bdrv_ref(s->to_replace);
}
/* TODO Translate this into child freeze system. */
error_setg(&s->replace_blocker,
"block device is in use by block-job-complete");
bdrv_op_block_all(s->to_replace, s->replace_blocker);
bdrv_ref(s->to_replace);
s->should_complete = true;
}
s->should_complete = true;
/* If the job is paused, it will be re-entered when it is resumed */
WITH_JOB_LOCK_GUARD() {
if (!job->paused) {