qmp: Add optional bool "unmap" to drive-mirror

If specified as "true", it allows discarding on target sectors where source is
not allocated.

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Fam Zheng 2015-06-08 13:56:08 +08:00 committed by Stefan Hajnoczi
parent ba3f0e2545
commit 0fc9f8ea28
6 changed files with 24 additions and 4 deletions

View File

@ -58,6 +58,7 @@ typedef struct MirrorBlockJob {
int in_flight; int in_flight;
int sectors_in_flight; int sectors_in_flight;
int ret; int ret;
bool unmap;
} MirrorBlockJob; } MirrorBlockJob;
typedef struct MirrorOp { typedef struct MirrorOp {
@ -652,6 +653,7 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
int64_t buf_size, int64_t buf_size,
BlockdevOnError on_source_error, BlockdevOnError on_source_error,
BlockdevOnError on_target_error, BlockdevOnError on_target_error,
bool unmap,
BlockCompletionFunc *cb, BlockCompletionFunc *cb,
void *opaque, Error **errp, void *opaque, Error **errp,
const BlockJobDriver *driver, const BlockJobDriver *driver,
@ -686,6 +688,7 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
s->base = base; s->base = base;
s->granularity = granularity; s->granularity = granularity;
s->buf_size = MAX(buf_size, granularity); s->buf_size = MAX(buf_size, granularity);
s->unmap = unmap;
s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp); s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp);
if (!s->dirty_bitmap) { if (!s->dirty_bitmap) {
@ -704,6 +707,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
int64_t speed, uint32_t granularity, int64_t buf_size, int64_t speed, uint32_t granularity, int64_t buf_size,
MirrorSyncMode mode, BlockdevOnError on_source_error, MirrorSyncMode mode, BlockdevOnError on_source_error,
BlockdevOnError on_target_error, BlockdevOnError on_target_error,
bool unmap,
BlockCompletionFunc *cb, BlockCompletionFunc *cb,
void *opaque, Error **errp) void *opaque, Error **errp)
{ {
@ -718,7 +722,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
base = mode == MIRROR_SYNC_MODE_TOP ? bs->backing_hd : NULL; base = mode == MIRROR_SYNC_MODE_TOP ? bs->backing_hd : NULL;
mirror_start_job(bs, target, replaces, mirror_start_job(bs, target, replaces,
speed, granularity, buf_size, speed, granularity, buf_size,
on_source_error, on_target_error, cb, opaque, errp, on_source_error, on_target_error, unmap, cb, opaque, errp,
&mirror_job_driver, is_none_mode, base); &mirror_job_driver, is_none_mode, base);
} }
@ -766,7 +770,7 @@ void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
bdrv_ref(base); bdrv_ref(base);
mirror_start_job(bs, base, NULL, speed, 0, 0, mirror_start_job(bs, base, NULL, speed, 0, 0,
on_error, on_error, cb, opaque, &local_err, on_error, on_error, false, cb, opaque, &local_err,
&commit_active_job_driver, false, base); &commit_active_job_driver, false, base);
if (local_err) { if (local_err) {
error_propagate(errp, local_err); error_propagate(errp, local_err);

View File

@ -2655,6 +2655,7 @@ void qmp_drive_mirror(const char *device, const char *target,
bool has_buf_size, int64_t buf_size, bool has_buf_size, int64_t buf_size,
bool has_on_source_error, BlockdevOnError on_source_error, bool has_on_source_error, BlockdevOnError on_source_error,
bool has_on_target_error, BlockdevOnError on_target_error, bool has_on_target_error, BlockdevOnError on_target_error,
bool has_unmap, bool unmap,
Error **errp) Error **errp)
{ {
BlockBackend *blk; BlockBackend *blk;
@ -2686,6 +2687,9 @@ void qmp_drive_mirror(const char *device, const char *target,
if (!has_buf_size) { if (!has_buf_size) {
buf_size = DEFAULT_MIRROR_BUF_SIZE; buf_size = DEFAULT_MIRROR_BUF_SIZE;
} }
if (!has_unmap) {
unmap = true;
}
if (granularity != 0 && (granularity < 512 || granularity > 1048576 * 64)) { if (granularity != 0 && (granularity < 512 || granularity > 1048576 * 64)) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "granularity", error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "granularity",
@ -2827,6 +2831,7 @@ void qmp_drive_mirror(const char *device, const char *target,
has_replaces ? replaces : NULL, has_replaces ? replaces : NULL,
speed, granularity, buf_size, sync, speed, granularity, buf_size, sync,
on_source_error, on_target_error, on_source_error, on_target_error,
unmap,
block_job_cb, bs, &local_err); block_job_cb, bs, &local_err);
if (local_err != NULL) { if (local_err != NULL) {
bdrv_unref(target_bs); bdrv_unref(target_bs);

2
hmp.c
View File

@ -1061,7 +1061,7 @@ void hmp_drive_mirror(Monitor *mon, const QDict *qdict)
false, NULL, false, NULL, false, NULL, false, NULL,
full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP, full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
true, mode, false, 0, false, 0, false, 0, true, mode, false, 0, false, 0, false, 0,
false, 0, false, 0, &err); false, 0, false, 0, false, true, &err);
hmp_handle_error(mon, &err); hmp_handle_error(mon, &err);
} }

View File

@ -612,6 +612,7 @@ void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
* @mode: Whether to collapse all images in the chain to the target. * @mode: Whether to collapse all images in the chain to the target.
* @on_source_error: The action to take upon error reading from the source. * @on_source_error: The action to take upon error reading from the source.
* @on_target_error: The action to take upon error writing to the target. * @on_target_error: The action to take upon error writing to the target.
* @unmap: Whether to unmap target where source sectors only contain zeroes.
* @cb: Completion function for the job. * @cb: Completion function for the job.
* @opaque: Opaque pointer value passed to @cb. * @opaque: Opaque pointer value passed to @cb.
* @errp: Error object. * @errp: Error object.
@ -626,6 +627,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
int64_t speed, uint32_t granularity, int64_t buf_size, int64_t speed, uint32_t granularity, int64_t buf_size,
MirrorSyncMode mode, BlockdevOnError on_source_error, MirrorSyncMode mode, BlockdevOnError on_source_error,
BlockdevOnError on_target_error, BlockdevOnError on_target_error,
bool unmap,
BlockCompletionFunc *cb, BlockCompletionFunc *cb,
void *opaque, Error **errp); void *opaque, Error **errp);

View File

@ -975,6 +975,11 @@
# @on-target-error: #optional the action to take on an error on the target, # @on-target-error: #optional the action to take on an error on the target,
# default 'report' (no limitations, since this applies to # default 'report' (no limitations, since this applies to
# a different block device than @device). # a different block device than @device).
# @unmap: #optional Whether to try to unmap target sectors where source has
# only zero. If true, and target unallocated sectors will read as zero,
# target image sectors will be unmapped; otherwise, zeroes will be
# written. Both will result in identical contents.
# Default is true. (Since 2.4)
# #
# Returns: nothing on success # Returns: nothing on success
# If @device is not a valid block device, DeviceNotFound # If @device is not a valid block device, DeviceNotFound
@ -987,7 +992,8 @@
'sync': 'MirrorSyncMode', '*mode': 'NewImageMode', 'sync': 'MirrorSyncMode', '*mode': 'NewImageMode',
'*speed': 'int', '*granularity': 'uint32', '*speed': 'int', '*granularity': 'uint32',
'*buf-size': 'int', '*on-source-error': 'BlockdevOnError', '*buf-size': 'int', '*on-source-error': 'BlockdevOnError',
'*on-target-error': 'BlockdevOnError' } } '*on-target-error': 'BlockdevOnError',
'*unmap': 'bool' } }
## ##
# @BlockDirtyBitmap # @BlockDirtyBitmap

View File

@ -1503,6 +1503,7 @@ EQMP
.args_type = "sync:s,device:B,target:s,speed:i?,mode:s?,format:s?," .args_type = "sync:s,device:B,target:s,speed:i?,mode:s?,format:s?,"
"node-name:s?,replaces:s?," "node-name:s?,replaces:s?,"
"on-source-error:s?,on-target-error:s?," "on-source-error:s?,on-target-error:s?,"
"unmap:b?,"
"granularity:i?,buf-size:i?", "granularity:i?,buf-size:i?",
.mhandler.cmd_new = qmp_marshal_input_drive_mirror, .mhandler.cmd_new = qmp_marshal_input_drive_mirror,
}, },
@ -1542,6 +1543,8 @@ Arguments:
(BlockdevOnError, default 'report') (BlockdevOnError, default 'report')
- "on-target-error": the action to take on an error on the target - "on-target-error": the action to take on an error on the target
(BlockdevOnError, default 'report') (BlockdevOnError, default 'report')
- "unmap": whether the target sectors should be discarded where source has only
zeroes. (json-bool, optional, default true)
The default value of the granularity is the image cluster size clamped 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 between 4096 and 65536, if the image format defines one. If the format