While blockdev-backup tried to verify before moving target's aio context, the same is missing for blockdev-mirror. Now that we have the right interface, fix this as well.
As a bonus, the aio context move is now conditional, which avoids some unnecessary operations in bdrv_set_aio_context. Signed-off-by: Fam Zheng <f...@redhat.com> --- block/mirror.c | 54 ++++++++++++++++++++++++++++++++---------------------- blockdev.c | 4 ---- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/block/mirror.c b/block/mirror.c index a3337ee..4eccb8d 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -1118,13 +1118,44 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs, bool auto_complete, const char *filter_node_name, Error **errp) { + AioContext *aio_context, *target_context; MirrorBlockJob *s; BlockDriverState *mirror_top_bs; + BlockBackend *target_blk; bool target_graph_mod; bool target_is_backing; Error *local_err = NULL; int ret; + /* No resize for the target either; while the mirror is still running, a + * consistent read isn't necessarily possible. We could possibly allow + * writes and graph modifications, though it would likely defeat the + * purpose of a mirror, so leave them blocked for now. + * + * In the case of active commit, things look a bit different, though, + * because the target is an already populated backing file in active use. + * We can allow anything except resize there.*/ + target_is_backing = bdrv_chain_contains(bs, target); + target_graph_mod = (backing_mode != MIRROR_LEAVE_BACKING_CHAIN); + target_blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE | + BLK_PERM_AIO_CONTEXT_CHANGE | + (target_graph_mod ? BLK_PERM_GRAPH_MOD : 0), + BLK_PERM_WRITE_UNCHANGED | + (target_is_backing ? BLK_PERM_CONSISTENT_READ | + BLK_PERM_WRITE | + BLK_PERM_GRAPH_MOD : 0)); + ret = blk_insert_bs(target_blk, target, errp); + if (ret < 0) { + blk_unref(target_blk); + return; + } + aio_context = bdrv_get_aio_context(bs); + target_context = bdrv_get_aio_context(target); + if (target_context != aio_context) { + aio_context_acquire(target_context); + blk_set_aio_context(target_blk, aio_context); + aio_context_release(target_context); + } if (granularity == 0) { granularity = bdrv_get_default_bitmap_granularity(target); } @@ -1179,28 +1210,7 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs, s->source = bs; s->mirror_top_bs = mirror_top_bs; - /* No resize for the target either; while the mirror is still running, a - * consistent read isn't necessarily possible. We could possibly allow - * writes and graph modifications, though it would likely defeat the - * purpose of a mirror, so leave them blocked for now. - * - * In the case of active commit, things look a bit different, though, - * because the target is an already populated backing file in active use. - * We can allow anything except resize there.*/ - target_is_backing = bdrv_chain_contains(bs, target); - target_graph_mod = (backing_mode != MIRROR_LEAVE_BACKING_CHAIN); - s->target = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE | - BLK_PERM_AIO_CONTEXT_CHANGE | - (target_graph_mod ? BLK_PERM_GRAPH_MOD : 0), - BLK_PERM_WRITE_UNCHANGED | - (target_is_backing ? BLK_PERM_CONSISTENT_READ | - BLK_PERM_WRITE | - BLK_PERM_GRAPH_MOD : 0)); - ret = blk_insert_bs(s->target, target, errp); - if (ret < 0) { - goto fail; - } - + s->target = target_blk; s->replaces = g_strdup(replaces); s->on_source_error = on_source_error; s->on_target_error = on_target_error; diff --git a/blockdev.c b/blockdev.c index e8f72a1..52d81c4 100644 --- a/blockdev.c +++ b/blockdev.c @@ -3545,8 +3545,6 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) goto out; } - bdrv_set_aio_context(target_bs, aio_context); - blockdev_mirror_common(arg->has_job_id ? arg->job_id : NULL, bs, target_bs, arg->has_replaces, arg->replaces, arg->sync, backing_mode, arg->has_speed, arg->speed, @@ -3597,8 +3595,6 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id, aio_context = bdrv_get_aio_context(bs); aio_context_acquire(aio_context); - bdrv_set_aio_context(target_bs, aio_context); - blockdev_mirror_common(has_job_id ? job_id : NULL, bs, target_bs, has_replaces, replaces, sync, backing_mode, has_speed, speed, -- 2.9.4