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 <[email protected]> --- block/mirror.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/block/mirror.c b/block/mirror.c index fa1d975eb9..2fcded9e93 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -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) { -- 2.47.3
