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>
Fiona Ebner committed
Mar 11, 2026 at 15:54 UTC
9ac85f4cc7995217db8f736733b990d6addcb036
1 file changed
+15
-13
block/mirror.c
+15
-13
@@ -1276,23 +1276,25 @@ static void mirror_complete(Job *job, Error **errp)
1276
return;
1277
}
1278
1279
- /* block all operations on to_replace bs */
1280
- if (s->replaces) {
1281
- s->to_replace = bdrv_find_node(s->replaces);
1282
- if (!s->to_replace) {
1283
- error_setg(errp, "Node name '%s' not found", s->replaces);
1284
- return;
1279
+ if (!s->should_complete) {
1280
+ /* block all operations on to_replace bs */
1281
+ if (s->replaces) {
1282
+ s->to_replace = bdrv_find_node(s->replaces);
1283
+ if (!s->to_replace) {
1284
+ error_setg(errp, "Node name '%s' not found", s->replaces);
1285
+ return;
1286
+ }
1287
+
1288
+ /* TODO Translate this into child freeze system. */
1289
+ error_setg(&s->replace_blocker,
1290
+ "block device is in use by block-job-complete");
1291
+ bdrv_op_block_all(s->to_replace, s->replace_blocker);
1292
+ bdrv_ref(s->to_replace);
1293
}
1294
1287
- /* TODO Translate this into child freeze system. */
1288
- error_setg(&s->replace_blocker,
1289
- "block device is in use by block-job-complete");
1290
- bdrv_op_block_all(s->to_replace, s->replace_blocker);
1291
- bdrv_ref(s->to_replace);
1295
+ s->should_complete = true;
1296
}
1297
1294
- s->should_complete = true;
1295
-
1298
/* If the job is paused, it will be re-entered when it is resumed */
1299
WITH_JOB_LOCK_GUARD() {
1300
if (!job->paused) {