qmp: Add blockdev-mirror command

This will start a mirror job from a named device to another named
device, its relation with drive-mirror is similar with blockdev-backup
to drive-backup.

In blockdev-mirror, the target node should be prepared by blockdev-add,
which will be responsible for assigning a name to the new node, so
we don't have 'node-name' parameter.

Signed-off-by: Fam Zheng <famz@redhat.com>
Acked-by: Markus Armbruster <armbru@redhat.com>
Message-id: 1450932306-13717-5-git-send-email-famz@redhat.com
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
stable-2.6
Fam Zheng 2015-12-24 12:45:05 +08:00 committed by Max Reitz
parent e40e5027f6
commit df92562e68
3 changed files with 159 additions and 1 deletions

View File

@ -3345,6 +3345,10 @@ static void blockdev_mirror_common(BlockDriverState *bs,
if (bdrv_op_is_blocked(target, BLOCK_OP_TYPE_MIRROR_TARGET, errp)) {
return;
}
if (target->blk) {
error_setg(errp, "Cannot mirror to an attached block device");
return;
}
if (!bs->backing && sync == MIRROR_SYNC_MODE_TOP) {
sync = MIRROR_SYNC_MODE_FULL;
@ -3518,6 +3522,64 @@ out:
aio_context_release(aio_context);
}
void qmp_blockdev_mirror(const char *device, const char *target,
bool has_replaces, const char *replaces,
MirrorSyncMode sync,
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,
Error **errp)
{
BlockDriverState *bs;
BlockBackend *blk;
BlockDriverState *target_bs;
AioContext *aio_context;
Error *local_err = NULL;
blk = blk_by_name(device);
if (!blk) {
error_setg(errp, "Device '%s' not found", device);
return;
}
bs = blk_bs(blk);
if (!bs) {
error_setg(errp, "Device '%s' has no media", device);
return;
}
target_bs = bdrv_lookup_bs(target, target, errp);
if (!target_bs) {
return;
}
aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(aio_context);
bdrv_ref(target_bs);
bdrv_set_aio_context(target_bs, aio_context);
blockdev_mirror_common(bs, target_bs,
has_replaces, replaces, sync,
has_speed, speed,
has_granularity, granularity,
has_buf_size, buf_size,
has_on_source_error, on_source_error,
has_on_target_error, on_target_error,
true, true,
&local_err);
if (local_err) {
error_propagate(errp, local_err);
bdrv_unref(target_bs);
}
aio_context_release(aio_context);
}
/* Get the block job for a given device name and acquire its AioContext */
static BlockJob *find_block_job(const char *device, AioContext **aio_context,
Error **errp)

View File

@ -1183,6 +1183,54 @@
{ 'command': 'block-dirty-bitmap-clear',
'data': 'BlockDirtyBitmap' }
##
# @blockdev-mirror
#
# Start mirroring a block device's writes to a new destination.
#
# @device: the name of the device whose writes should be mirrored.
#
# @target: the id or node-name of the block device to mirror to. This mustn't be
# attached to guest.
#
# @replaces: #optional with sync=full graph node name to be replaced by the new
# image when a whole image copy is done. This can be used to repair
# broken Quorum files.
#
# @speed: #optional the maximum speed, in bytes per second
#
# @sync: what parts of the disk image should be copied to the destination
# (all the disk, only the sectors allocated in the topmost image, or
# only new I/O).
#
# @granularity: #optional granularity of the dirty bitmap, default is 64K
# if the image format doesn't have clusters, 4K if the clusters
# are smaller than that, else the cluster size. Must be a
# power of 2 between 512 and 64M
#
# @buf-size: #optional maximum amount of data in flight from source to
# target
#
# @on-source-error: #optional the action to take on an error on the source,
# default 'report'. 'stop' and 'enospc' can only be used
# if the block device supports io-status (see BlockInfo).
#
# @on-target-error: #optional the action to take on an error on the target,
# default 'report' (no limitations, since this applies to
# a different block device than @device).
#
# Returns: nothing on success.
#
# Since 2.6
##
{ 'command': 'blockdev-mirror',
'data': { 'device': 'str', 'target': 'str',
'*replaces': 'str',
'sync': 'MirrorSyncMode',
'*speed': 'int', '*granularity': 'uint32',
'*buf-size': 'int', '*on-source-error': 'BlockdevOnError',
'*on-target-error': 'BlockdevOnError' } }
##
# @block_set_io_throttle:
#

View File

@ -1635,7 +1635,7 @@ Arguments:
- "speed": maximum speed of the streaming job, in bytes per second
(json-int)
- "granularity": granularity of the dirty bitmap, in bytes (json-int, optional)
- "buf_size": maximum amount of data in flight from source to target, in bytes
- "buf-size": maximum amount of data in flight from source to target, in bytes
(json-int, default 10M)
- "sync": what parts of the disk image should be copied to the destination;
possibilities include "full" for all the disk, "top" for only the sectors
@ -1664,6 +1664,54 @@ Example:
EQMP
{
.name = "blockdev-mirror",
.args_type = "sync:s,device:B,target:B,replaces:s?,speed:i?,"
"on-source-error:s?,on-target-error:s?,"
"granularity:i?,buf-size:i?",
.mhandler.cmd_new = qmp_marshal_blockdev_mirror,
},
SQMP
blockdev-mirror
------------
Start mirroring a block device's writes to another block device. target
specifies the target of mirror operation.
Arguments:
- "device": device name to operate on (json-string)
- "target": device name to mirror to (json-string)
- "replaces": the block driver node name to replace when finished
(json-string, optional)
- "speed": maximum speed of the streaming job, in bytes per second
(json-int)
- "granularity": granularity of the dirty bitmap, in bytes (json-int, optional)
- "buf_size": maximum amount of data in flight from source to target, in bytes
(json-int, default 10M)
- "sync": what parts of the disk image should be copied to the destination;
possibilities include "full" for all the disk, "top" for only the sectors
allocated in the topmost image, or "none" to only replicate new I/O
(MirrorSyncMode).
- "on-source-error": the action to take on an error on the source
(BlockdevOnError, default 'report')
- "on-target-error": the action to take on an error on the target
(BlockdevOnError, default 'report')
The default value of the granularity is the image cluster size clamped
between 4096 and 65536, if the image format defines one. If the format
does not define a cluster size, the default value of the granularity
is 65536.
Example:
-> { "execute": "blockdev-mirror", "arguments": { "device": "ide-hd0",
"target": "target0",
"sync": "full" } }
<- { "return": {} }
EQMP
{
.name = "change-backing-file",
.args_type = "device:s,image-node-name:s,backing-file:s",