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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user