static void mirror_exit(BlockJob *job, void *opaque)

{

    MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);

    MirrorExitData *data = opaque;

    AioContext *replace_aio_context = NULL;

    BlockDriverState *src = s->common.bs;



    /* Make sure that the source BDS doesn't go away before we called

     * block_job_completed(). */

    bdrv_ref(src);



    if (s->to_replace) {

        replace_aio_context = bdrv_get_aio_context(s->to_replace);

        aio_context_acquire(replace_aio_context);

    }



    if (s->should_complete && data->ret == 0) {

        BlockDriverState *to_replace = s->common.bs;

        if (s->to_replace) {

            to_replace = s->to_replace;

        }



        /* This was checked in mirror_start_job(), but meanwhile one of the

         * nodes could have been newly attached to a BlockBackend. */

        if (to_replace->blk && s->target->blk) {

            error_report("block job: Can't create node with two BlockBackends");

            data->ret = -EINVAL;

            goto out;

        }



        if (bdrv_get_flags(s->target) != bdrv_get_flags(to_replace)) {

            bdrv_reopen(s->target, bdrv_get_flags(to_replace), NULL);

        }

        bdrv_replace_in_backing_chain(to_replace, s->target);

    }



out:

    if (s->to_replace) {

        bdrv_op_unblock_all(s->to_replace, s->replace_blocker);

        error_free(s->replace_blocker);

        bdrv_unref(s->to_replace);

    }

    if (replace_aio_context) {

        aio_context_release(replace_aio_context);

    }

    g_free(s->replaces);

    bdrv_op_unblock_all(s->target, s->common.blocker);

    bdrv_unref(s->target);

    block_job_completed(&s->common, data->ret);

    g_free(data);

    bdrv_drained_end(src);

    if (qemu_get_aio_context() == bdrv_get_aio_context(src)) {

        aio_enable_external(iohandler_get_aio_context());

    }

    bdrv_unref(src);

}

static void mirror_exit(BlockJob *job, void *opaque)

{

    MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);

    MirrorExitData *data = opaque;

    AioContext *replace_aio_context = NULL;

    BlockDriverState *src = s->common.bs;



    



    bdrv_ref(src);



    if (s->to_replace) {

        replace_aio_context = bdrv_get_aio_context(s->to_replace);

        aio_context_acquire(replace_aio_context);

    }



    if (s->should_complete && data->ret == 0) {

        BlockDriverState *to_replace = s->common.bs;

        if (s->to_replace) {

            to_replace = s->to_replace;

        }



        



        if (to_replace->blk && s->target->blk) {

            error_report("block job: Can't create node with two BlockBackends");

            data->ret = -EINVAL;

            goto out;

        }



        if (bdrv_get_flags(s->target) != bdrv_get_flags(to_replace)) {

            bdrv_reopen(s->target, bdrv_get_flags(to_replace), NULL);

        }

        bdrv_replace_in_backing_chain(to_replace, s->target);

    }



out:

    if (s->to_replace) {

        bdrv_op_unblock_all(s->to_replace, s->replace_blocker);

        error_free(s->replace_blocker);

        bdrv_unref(s->to_replace);

    }

    if (replace_aio_context) {

        aio_context_release(replace_aio_context);

    }

    g_free(s->replaces);

    bdrv_op_unblock_all(s->target, s->common.blocker);

    bdrv_unref(s->target);

    block_job_completed(&s->common, data->ret);

    g_free(data);

    bdrv_drained_end(src);

    if (qemu_get_aio_context() == bdrv_get_aio_context(src)) {

        aio_enable_external(iohandler_get_aio_context());

    }

    bdrv_unref(src);

}

static void FUNC_0(BlockJob *VAR_0, void *VAR_1)

{

    MirrorBlockJob *s = container_of(VAR_0, MirrorBlockJob, common);

    MirrorExitData *data = VAR_1;

    AioContext *replace_aio_context = NULL;

    BlockDriverState *src = s->common.bs;



    



    bdrv_ref(src);



    if (s->to_replace) {

        replace_aio_context = bdrv_get_aio_context(s->to_replace);

        aio_context_acquire(replace_aio_context);

    }



    if (s->should_complete && data->ret == 0) {

        BlockDriverState *to_replace = s->common.bs;

        if (s->to_replace) {

            to_replace = s->to_replace;

        }



        



        if (to_replace->blk && s->target->blk) {

            error_report("block VAR_0: Can't create node with two BlockBackends");

            data->ret = -EINVAL;

            goto out;

        }



        if (bdrv_get_flags(s->target) != bdrv_get_flags(to_replace)) {

            bdrv_reopen(s->target, bdrv_get_flags(to_replace), NULL);

        }

        bdrv_replace_in_backing_chain(to_replace, s->target);

    }



out:

    if (s->to_replace) {

        bdrv_op_unblock_all(s->to_replace, s->replace_blocker);

        error_free(s->replace_blocker);

        bdrv_unref(s->to_replace);

    }

    if (replace_aio_context) {

        aio_context_release(replace_aio_context);

    }

    g_free(s->replaces);

    bdrv_op_unblock_all(s->target, s->common.blocker);

    bdrv_unref(s->target);

    block_job_completed(&s->common, data->ret);

    g_free(data);

    bdrv_drained_end(src);

    if (qemu_get_aio_context() == bdrv_get_aio_context(src)) {

        aio_enable_external(iohandler_get_aio_context());

    }

    bdrv_unref(src);

}

static void FUNC_0(BlockJob *VAR_0, void *VAR_1)
{ MirrorBlockJob *s = container_of(VAR_0, MirrorBlockJob, common); MirrorExitData *data = VAR_1; AioContext *replace_aio_context = NULL; BlockDriverState *src = s->common.bs; bdrv_ref(src); if (s->to_replace) { replace_aio_context = bdrv_get_aio_context(s->to_replace); aio_context_acquire(replace_aio_context); } if (s->should_complete && data->ret == 0) { BlockDriverState *to_replace = s->common.bs; if (s->to_replace) { to_replace = s->to_replace; } if (to_replace->blk && s->target->blk) { error_report("block VAR_0: Can't create node with two BlockBackends"); data->ret = -EINVAL; goto out; } if (bdrv_get_flags(s->target) != bdrv_get_flags(to_replace)) { bdrv_reopen(s->target, bdrv_get_flags(to_replace), NULL); } bdrv_replace_in_backing_chain(to_replace, s->target); } out:
if (s->to_replace) { bdrv_op_unblock_all(s->to_replace, s->replace_blocker); error_free(s->replace_blocker); bdrv_unref(s->to_replace); } if (replace_aio_context) { aio_context_release(replace_aio_context); } g_free(s->replaces); bdrv_op_unblock_all(s->target, s->common.blocker); bdrv_unref(s->target); block_job_completed(&s->common, data->ret); g_free(data); bdrv_drained_end(src); if (qemu_get_aio_context() == bdrv_get_aio_context(src)) { aio_enable_external(iohandler_get_aio_context()); } bdrv_unref(src); }