block: Extract blockdev part of qmp_drive_mirror

This is the part that will be reused by blockdev-mirror.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Message-id: 1450932306-13717-3-git-send-email-famz@redhat.com
Signed-off-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
Fam Zheng 2015-12-24 12:45:03 +08:00 committed by Max Reitz
parent 05e4d14bf3
commit 4193cdd771

View File

@ -3291,29 +3291,23 @@ void qmp_blockdev_backup(const char *device, const char *target,
NULL, errp); NULL, errp);
} }
void qmp_drive_mirror(const char *device, const char *target, /* Parameter check and block job starting for drive mirroring.
bool has_format, const char *format, * Caller should hold @device and @target's aio context (must be the same).
bool has_node_name, const char *node_name, **/
bool has_replaces, const char *replaces, static void blockdev_mirror_common(BlockDriverState *bs,
enum MirrorSyncMode sync, BlockDriverState *target,
bool has_mode, enum NewImageMode mode, bool has_replaces, const char *replaces,
bool has_speed, int64_t speed, enum MirrorSyncMode sync,
bool has_granularity, uint32_t granularity, bool has_speed, int64_t speed,
bool has_buf_size, int64_t buf_size, bool has_granularity, uint32_t granularity,
bool has_on_source_error, BlockdevOnError on_source_error, bool has_buf_size, int64_t buf_size,
bool has_on_target_error, BlockdevOnError on_target_error, bool has_on_source_error,
bool has_unmap, bool unmap, BlockdevOnError on_source_error,
Error **errp) bool has_on_target_error,
BlockdevOnError on_target_error,
bool has_unmap, bool unmap,
Error **errp)
{ {
BlockBackend *blk;
BlockDriverState *bs;
BlockDriverState *source, *target_bs;
AioContext *aio_context;
Error *local_err = NULL;
QDict *options;
int flags;
int64_t size;
int ret;
if (!has_speed) { if (!has_speed) {
speed = 0; speed = 0;
@ -3324,9 +3318,6 @@ void qmp_drive_mirror(const char *device, const char *target,
if (!has_on_target_error) { if (!has_on_target_error) {
on_target_error = BLOCKDEV_ON_ERROR_REPORT; on_target_error = BLOCKDEV_ON_ERROR_REPORT;
} }
if (!has_mode) {
mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
}
if (!has_granularity) { if (!has_granularity) {
granularity = 0; granularity = 0;
} }
@ -3348,6 +3339,48 @@ void qmp_drive_mirror(const char *device, const char *target,
return; return;
} }
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_MIRROR_SOURCE, errp)) {
return;
}
if (!bs->backing && sync == MIRROR_SYNC_MODE_TOP) {
sync = MIRROR_SYNC_MODE_FULL;
}
/* pass the node name to replace to mirror start since it's loose coupling
* and will allow to check whether the node still exist at mirror completion
*/
mirror_start(bs, target,
has_replaces ? replaces : NULL,
speed, granularity, buf_size, sync,
on_source_error, on_target_error, unmap,
block_job_cb, bs, errp);
}
void qmp_drive_mirror(const char *device, const char *target,
bool has_format, const char *format,
bool has_node_name, const char *node_name,
bool has_replaces, const char *replaces,
enum MirrorSyncMode sync,
bool has_mode, enum NewImageMode mode,
bool has_speed, int64_t speed,
bool has_granularity, uint32_t granularity,
bool has_buf_size, int64_t buf_size,
bool has_on_source_error, BlockdevOnError on_source_error,
bool has_on_target_error, BlockdevOnError on_target_error,
bool has_unmap, bool unmap,
Error **errp)
{
BlockDriverState *bs;
BlockBackend *blk;
BlockDriverState *source, *target_bs;
AioContext *aio_context;
Error *local_err = NULL;
QDict *options = NULL;
int flags;
int64_t size;
int ret;
blk = blk_by_name(device); blk = blk_by_name(device);
if (!blk) { if (!blk) {
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
@ -3363,15 +3396,14 @@ void qmp_drive_mirror(const char *device, const char *target,
goto out; goto out;
} }
bs = blk_bs(blk); bs = blk_bs(blk);
if (!has_mode) {
mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
}
if (!has_format) { if (!has_format) {
format = mode == NEW_IMAGE_MODE_EXISTING ? NULL : bs->drv->format_name; format = mode == NEW_IMAGE_MODE_EXISTING ? NULL : bs->drv->format_name;
} }
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_MIRROR_SOURCE, errp)) {
goto out;
}
flags = bs->open_flags | BDRV_O_RDWR; flags = bs->open_flags | BDRV_O_RDWR;
source = backing_bs(bs); source = backing_bs(bs);
if (!source && sync == MIRROR_SYNC_MODE_TOP) { if (!source && sync == MIRROR_SYNC_MODE_TOP) {
@ -3466,21 +3498,19 @@ void qmp_drive_mirror(const char *device, const char *target,
bdrv_set_aio_context(target_bs, aio_context); bdrv_set_aio_context(target_bs, aio_context);
/* pass the node name to replace to mirror start since it's loose coupling blockdev_mirror_common(bs, target_bs,
* and will allow to check whether the node still exist at mirror completion has_replaces, replaces, sync,
*/ has_speed, speed,
mirror_start(bs, target_bs, has_granularity, granularity,
has_replaces ? replaces : NULL, has_buf_size, buf_size,
speed, granularity, buf_size, sync, has_on_source_error, on_source_error,
on_source_error, on_target_error, has_on_target_error, on_target_error,
unmap, has_unmap, unmap,
block_job_cb, bs, &local_err); &local_err);
if (local_err != NULL) { if (local_err) {
bdrv_unref(target_bs);
error_propagate(errp, local_err); error_propagate(errp, local_err);
goto out; bdrv_unref(target_bs);
} }
out: out:
aio_context_release(aio_context); aio_context_release(aio_context);
} }