mirror of https://github.com/xemu-project/xemu.git
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:
parent
ba3f0e2545
commit
0fc9f8ea28
|
@ -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);
|
||||||
|
|
|
@ -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
2
hmp.c
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue