void qmp_drive_mirror(DriveMirror *arg, Error **errp)

{

    BlockDriverState *bs;

    BlockDriverState *source, *target_bs;

    AioContext *aio_context;

    BlockMirrorBackingMode backing_mode;

    Error *local_err = NULL;

    QDict *options = NULL;

    int flags;

    int64_t size;

    const char *format = arg->format;



    bs = qmp_get_root_bs(arg->device, errp);

    if (!bs) {

        return;

    }



    aio_context = bdrv_get_aio_context(bs);

    aio_context_acquire(aio_context);



    if (!arg->has_mode) {

        arg->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;

    }



    if (!arg->has_format) {

        format = (arg->mode == NEW_IMAGE_MODE_EXISTING

                  ? NULL : bs->drv->format_name);

    }



    flags = bs->open_flags | BDRV_O_RDWR;

    source = backing_bs(bs);

    if (!source && arg->sync == MIRROR_SYNC_MODE_TOP) {

        arg->sync = MIRROR_SYNC_MODE_FULL;

    }

    if (arg->sync == MIRROR_SYNC_MODE_NONE) {

        source = bs;

    }



    size = bdrv_getlength(bs);

    if (size < 0) {

        error_setg_errno(errp, -size, "bdrv_getlength failed");

        goto out;

    }



    if (arg->has_replaces) {

        BlockDriverState *to_replace_bs;

        AioContext *replace_aio_context;

        int64_t replace_size;



        if (!arg->has_node_name) {

            error_setg(errp, "a node-name must be provided when replacing a"

                             " named node of the graph");

            goto out;

        }



        to_replace_bs = check_to_replace_node(bs, arg->replaces, &local_err);



        if (!to_replace_bs) {

            error_propagate(errp, local_err);

            goto out;

        }



        replace_aio_context = bdrv_get_aio_context(to_replace_bs);

        aio_context_acquire(replace_aio_context);

        replace_size = bdrv_getlength(to_replace_bs);

        aio_context_release(replace_aio_context);



        if (size != replace_size) {

            error_setg(errp, "cannot replace image with a mirror image of "

                             "different size");

            goto out;

        }

    }



    if (arg->mode == NEW_IMAGE_MODE_ABSOLUTE_PATHS) {

        backing_mode = MIRROR_SOURCE_BACKING_CHAIN;

    } else {

        backing_mode = MIRROR_OPEN_BACKING_CHAIN;

    }



    if ((arg->sync == MIRROR_SYNC_MODE_FULL || !source)

        && arg->mode != NEW_IMAGE_MODE_EXISTING)

    {

        /* create new image w/o backing file */

        assert(format);

        bdrv_img_create(arg->target, format,

                        NULL, NULL, NULL, size, flags, false, &local_err);

    } else {

        switch (arg->mode) {

        case NEW_IMAGE_MODE_EXISTING:

            break;

        case NEW_IMAGE_MODE_ABSOLUTE_PATHS:

            /* create new image with backing file */

            bdrv_img_create(arg->target, format,

                            source->filename,

                            source->drv->format_name,

                            NULL, size, flags, false, &local_err);

            break;

        default:

            abort();

        }

    }



    if (local_err) {

        error_propagate(errp, local_err);

        goto out;

    }



    options = qdict_new();

    if (arg->has_node_name) {

        qdict_put_str(options, "node-name", arg->node_name);

    }

    if (format) {

        qdict_put_str(options, "driver", format);

    }



    /* Mirroring takes care of copy-on-write using the source's backing

     * file.

     */

    target_bs = bdrv_open(arg->target, NULL, options,

                          flags | BDRV_O_NO_BACKING, errp);

    if (!target_bs) {

        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,

                           arg->has_granularity, arg->granularity,

                           arg->has_buf_size, arg->buf_size,

                           arg->has_on_source_error, arg->on_source_error,

                           arg->has_on_target_error, arg->on_target_error,

                           arg->has_unmap, arg->unmap,

                           false, NULL,

                           &local_err);

    bdrv_unref(target_bs);

    error_propagate(errp, local_err);

out:

    aio_context_release(aio_context);

}

void qmp_drive_mirror(DriveMirror *arg, Error **errp)

{

    BlockDriverState *bs;

    BlockDriverState *source, *target_bs;

    AioContext *aio_context;

    BlockMirrorBackingMode backing_mode;

    Error *local_err = NULL;

    QDict *options = NULL;

    int flags;

    int64_t size;

    const char *format = arg->format;



    bs = qmp_get_root_bs(arg->device, errp);

    if (!bs) {

        return;

    }



    aio_context = bdrv_get_aio_context(bs);

    aio_context_acquire(aio_context);



    if (!arg->has_mode) {

        arg->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;

    }



    if (!arg->has_format) {

        format = (arg->mode == NEW_IMAGE_MODE_EXISTING

                  ? NULL : bs->drv->format_name);

    }



    flags = bs->open_flags | BDRV_O_RDWR;

    source = backing_bs(bs);

    if (!source && arg->sync == MIRROR_SYNC_MODE_TOP) {

        arg->sync = MIRROR_SYNC_MODE_FULL;

    }

    if (arg->sync == MIRROR_SYNC_MODE_NONE) {

        source = bs;

    }



    size = bdrv_getlength(bs);

    if (size < 0) {

        error_setg_errno(errp, -size, "bdrv_getlength failed");

        goto out;

    }



    if (arg->has_replaces) {

        BlockDriverState *to_replace_bs;

        AioContext *replace_aio_context;

        int64_t replace_size;



        if (!arg->has_node_name) {

            error_setg(errp, "a node-name must be provided when replacing a"

                             " named node of the graph");

            goto out;

        }



        to_replace_bs = check_to_replace_node(bs, arg->replaces, &local_err);



        if (!to_replace_bs) {

            error_propagate(errp, local_err);

            goto out;

        }



        replace_aio_context = bdrv_get_aio_context(to_replace_bs);

        aio_context_acquire(replace_aio_context);

        replace_size = bdrv_getlength(to_replace_bs);

        aio_context_release(replace_aio_context);



        if (size != replace_size) {

            error_setg(errp, "cannot replace image with a mirror image of "

                             "different size");

            goto out;

        }

    }



    if (arg->mode == NEW_IMAGE_MODE_ABSOLUTE_PATHS) {

        backing_mode = MIRROR_SOURCE_BACKING_CHAIN;

    } else {

        backing_mode = MIRROR_OPEN_BACKING_CHAIN;

    }



    if ((arg->sync == MIRROR_SYNC_MODE_FULL || !source)

        && arg->mode != NEW_IMAGE_MODE_EXISTING)

    {

        

        assert(format);

        bdrv_img_create(arg->target, format,

                        NULL, NULL, NULL, size, flags, false, &local_err);

    } else {

        switch (arg->mode) {

        case NEW_IMAGE_MODE_EXISTING:

            break;

        case NEW_IMAGE_MODE_ABSOLUTE_PATHS:

            

            bdrv_img_create(arg->target, format,

                            source->filename,

                            source->drv->format_name,

                            NULL, size, flags, false, &local_err);

            break;

        default:

            abort();

        }

    }



    if (local_err) {

        error_propagate(errp, local_err);

        goto out;

    }



    options = qdict_new();

    if (arg->has_node_name) {

        qdict_put_str(options, "node-name", arg->node_name);

    }

    if (format) {

        qdict_put_str(options, "driver", format);

    }



    





    target_bs = bdrv_open(arg->target, NULL, options,

                          flags | BDRV_O_NO_BACKING, errp);

    if (!target_bs) {

        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,

                           arg->has_granularity, arg->granularity,

                           arg->has_buf_size, arg->buf_size,

                           arg->has_on_source_error, arg->on_source_error,

                           arg->has_on_target_error, arg->on_target_error,

                           arg->has_unmap, arg->unmap,

                           false, NULL,

                           &local_err);

    bdrv_unref(target_bs);

    error_propagate(errp, local_err);

out:

    aio_context_release(aio_context);

}

    target_bs = bdrv_open(arg->target, NULL, options,                           flags | BDRV_O_NO_BACKING, errp);
void FUNC_0(DriveMirror *VAR_0, Error **VAR_1)

{

    BlockDriverState *bs;

    BlockDriverState *source, *target_bs;

    AioContext *aio_context;

    BlockMirrorBackingMode backing_mode;

    Error *local_err = NULL;

    QDict *options = NULL;

    int VAR_2;

    int64_t size;

    const char *VAR_3 = VAR_0->VAR_3;



    bs = qmp_get_root_bs(VAR_0->device, VAR_1);

    if (!bs) {

        return;

    }



    aio_context = bdrv_get_aio_context(bs);

    aio_context_acquire(aio_context);



    if (!VAR_0->has_mode) {

        VAR_0->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;

    }



    if (!VAR_0->has_format) {

        VAR_3 = (VAR_0->mode == NEW_IMAGE_MODE_EXISTING

                  ? NULL : bs->drv->format_name);

    }



    VAR_2 = bs->open_flags | BDRV_O_RDWR;

    source = backing_bs(bs);

    if (!source && VAR_0->sync == MIRROR_SYNC_MODE_TOP) {

        VAR_0->sync = MIRROR_SYNC_MODE_FULL;

    }

    if (VAR_0->sync == MIRROR_SYNC_MODE_NONE) {

        source = bs;

    }



    size = bdrv_getlength(bs);

    if (size < 0) {

        error_setg_errno(VAR_1, -size, "bdrv_getlength failed");

        goto out;

    }



    if (VAR_0->has_replaces) {

        BlockDriverState *to_replace_bs;

        AioContext *replace_aio_context;

        int64_t replace_size;



        if (!VAR_0->has_node_name) {

            error_setg(VAR_1, "a node-name must be provided when replacing a"

                             " named node of the graph");

            goto out;

        }



        to_replace_bs = check_to_replace_node(bs, VAR_0->replaces, &local_err);



        if (!to_replace_bs) {

            error_propagate(VAR_1, local_err);

            goto out;

        }



        replace_aio_context = bdrv_get_aio_context(to_replace_bs);

        aio_context_acquire(replace_aio_context);

        replace_size = bdrv_getlength(to_replace_bs);

        aio_context_release(replace_aio_context);



        if (size != replace_size) {

            error_setg(VAR_1, "cannot replace image with a mirror image of "

                             "different size");

            goto out;

        }

    }



    if (VAR_0->mode == NEW_IMAGE_MODE_ABSOLUTE_PATHS) {

        backing_mode = MIRROR_SOURCE_BACKING_CHAIN;

    } else {

        backing_mode = MIRROR_OPEN_BACKING_CHAIN;

    }



    if ((VAR_0->sync == MIRROR_SYNC_MODE_FULL || !source)

        && VAR_0->mode != NEW_IMAGE_MODE_EXISTING)

    {

        

        assert(VAR_3);

        bdrv_img_create(VAR_0->target, VAR_3,

                        NULL, NULL, NULL, size, VAR_2, false, &local_err);

    } else {

        switch (VAR_0->mode) {

        case NEW_IMAGE_MODE_EXISTING:

            break;

        case NEW_IMAGE_MODE_ABSOLUTE_PATHS:

            

            bdrv_img_create(VAR_0->target, VAR_3,

                            source->filename,

                            source->drv->format_name,

                            NULL, size, VAR_2, false, &local_err);

            break;

        default:

            abort();

        }

    }



    if (local_err) {

        error_propagate(VAR_1, local_err);

        goto out;

    }



    options = qdict_new();

    if (VAR_0->has_node_name) {

        qdict_put_str(options, "node-name", VAR_0->node_name);

    }

    if (VAR_3) {

        qdict_put_str(options, "driver", VAR_3);

    }



    





    target_bs = bdrv_open(VAR_0->target, NULL, options,

                          VAR_2 | BDRV_O_NO_BACKING, VAR_1);

    if (!target_bs) {

        goto out;

    }



    bdrv_set_aio_context(target_bs, aio_context);



    blockdev_mirror_common(VAR_0->has_job_id ? VAR_0->job_id : NULL, bs, target_bs,

                           VAR_0->has_replaces, VAR_0->replaces, VAR_0->sync,

                           backing_mode, VAR_0->has_speed, VAR_0->speed,

                           VAR_0->has_granularity, VAR_0->granularity,

                           VAR_0->has_buf_size, VAR_0->buf_size,

                           VAR_0->has_on_source_error, VAR_0->on_source_error,

                           VAR_0->has_on_target_error, VAR_0->on_target_error,

                           VAR_0->has_unmap, VAR_0->unmap,

                           false, NULL,

                           &local_err);

    bdrv_unref(target_bs);

    error_propagate(VAR_1, local_err);

out:

    aio_context_release(aio_context);

}

void FUNC_0(DriveMirror *VAR_0, Error **VAR_1)
{ BlockDriverState *bs; BlockDriverState *source, *target_bs; AioContext *aio_context; BlockMirrorBackingMode backing_mode; Error *local_err = NULL; QDict *options = NULL; int VAR_2; int64_t size; const char *VAR_3 = VAR_0->VAR_3; bs = qmp_get_root_bs(VAR_0->device, VAR_1); if (!bs) { return; } aio_context = bdrv_get_aio_context(bs); aio_context_acquire(aio_context); if (!VAR_0->has_mode) { VAR_0->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; } if (!VAR_0->has_format) { VAR_3 = (VAR_0->mode == NEW_IMAGE_MODE_EXISTING
? NULL : bs->drv->format_name); } VAR_2 = bs->open_flags | BDRV_O_RDWR; source = backing_bs(bs); if (!source && VAR_0->sync == MIRROR_SYNC_MODE_TOP) { VAR_0->sync = MIRROR_SYNC_MODE_FULL; } if (VAR_0->sync == MIRROR_SYNC_MODE_NONE) { source = bs; } size = bdrv_getlength(bs); if (size < 0) { error_setg_errno(VAR_1, -size, "bdrv_getlength failed"); goto out; } if (VAR_0->has_replaces) { BlockDriverState *to_replace_bs; AioContext *replace_aio_context; int64_t replace_size; if (!VAR_0->has_node_name) { error_setg(VAR_1, "a node-name must be provided when replacing a"
" named node of the graph"); goto out; } to_replace_bs = check_to_replace_node(bs, VAR_0->replaces, &local_err); if (!to_replace_bs) { error_propagate(VAR_1, local_err); goto out; } replace_aio_context = bdrv_get_aio_context(to_replace_bs); aio_context_acquire(replace_aio_context); replace_size = bdrv_getlength(to_replace_bs); aio_context_release(replace_aio_context); if (size != replace_size) { error_setg(VAR_1, "cannot replace image with a mirror image of "
"different size"); goto out; } } if (VAR_0->mode == NEW_IMAGE_MODE_ABSOLUTE_PATHS) { backing_mode = MIRROR_SOURCE_BACKING_CHAIN; } else { backing_mode = MIRROR_OPEN_BACKING_CHAIN; } if ((VAR_0->sync == MIRROR_SYNC_MODE_FULL || !source)
&& VAR_0->mode != NEW_IMAGE_MODE_EXISTING)
{ assert(VAR_3); bdrv_img_create(VAR_0->target, VAR_3,
NULL, NULL, NULL, size, VAR_2, false, &local_err); } else { switch (VAR_0->mode) { case NEW_IMAGE_MODE_EXISTING:
break; case NEW_IMAGE_MODE_ABSOLUTE_PATHS:
bdrv_img_create(VAR_0->target, VAR_3,
source->filename,
source->drv->format_name,
NULL, size, VAR_2, false, &local_err); break; default:
abort(); } } if (local_err) { error_propagate(VAR_1, local_err); goto out; } options = qdict_new(); if (VAR_0->has_node_name) { qdict_put_str(options, "node-name", VAR_0->node_name); } if (VAR_3) { qdict_put_str(options, "driver", VAR_3); } target_bs = bdrv_open(VAR_0->target, NULL, options,
VAR_2 | BDRV_O_NO_BACKING, VAR_1); if (!target_bs) { goto out; } bdrv_set_aio_context(target_bs, aio_context); blockdev_mirror_common(VAR_0->has_job_id ? VAR_0->job_id : NULL, bs, target_bs,
VAR_0->has_replaces, VAR_0->replaces, VAR_0->sync,
backing_mode, VAR_0->has_speed, VAR_0->speed,
VAR_0->has_granularity, VAR_0->granularity,
VAR_0->has_buf_size, VAR_0->buf_size,
VAR_0->has_on_source_error, VAR_0->on_source_error,
VAR_0->has_on_target_error, VAR_0->on_target_error,
VAR_0->has_unmap, VAR_0->unmap,
false, NULL,
&local_err); bdrv_unref(target_bs); error_propagate(VAR_1, local_err); out:
aio_context_release(aio_context); }