qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 1/2] qapi: Add "detect-zeroes" option to drive-mirro


From: Fam Zheng
Subject: [Qemu-devel] [PATCH 1/2] qapi: Add "detect-zeroes" option to drive-mirror
Date: Mon, 8 Jun 2015 15:06:24 +0800

The new optional flag defaults to true, in which case, mirror job would
check the read sectors and use sparse write if they are zero.  Otherwise
data will be fully copied.

Signed-off-by: Fam Zheng <address@hidden>
---
 block/mirror.c            | 21 +++++++++++++++------
 blockdev.c                |  6 +++++-
 hmp.c                     |  2 +-
 include/block/block_int.h |  3 ++-
 qapi/block-core.json      |  4 +++-
 qmp-commands.hx           |  4 +++-
 6 files changed, 29 insertions(+), 11 deletions(-)

diff --git a/block/mirror.c b/block/mirror.c
index 3c38695..261373c 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -58,6 +58,7 @@ typedef struct MirrorBlockJob {
     int sectors_in_flight;
     int ret;
     bool unmap;
+    bool detect_zeroes;
 } MirrorBlockJob;
 
 typedef struct MirrorOp {
@@ -153,8 +154,14 @@ static void mirror_read_complete(void *opaque, int ret)
         mirror_iteration_done(op, ret);
         return;
     }
-    bdrv_aio_writev(s->target, op->sector_num, &op->qiov, op->nb_sectors,
-                    mirror_write_complete, op);
+    if (s->detect_zeroes && qemu_iovec_is_zero(&op->qiov)) {
+        bdrv_aio_write_zeroes(s->target, op->sector_num, op->nb_sectors,
+                              s->unmap ? BDRV_REQ_MAY_UNMAP : 0,
+                              mirror_write_complete, op);
+    } else {
+        bdrv_aio_writev(s->target, op->sector_num, &op->qiov, op->nb_sectors,
+                        mirror_write_complete, op);
+    }
 }
 
 static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
@@ -668,7 +675,7 @@ static void mirror_start_job(BlockDriverState *bs, 
BlockDriverState *target,
                              int64_t buf_size,
                              BlockdevOnError on_source_error,
                              BlockdevOnError on_target_error,
-                             bool unmap,
+                             bool unmap, bool detect_zeroes,
                              BlockCompletionFunc *cb,
                              void *opaque, Error **errp,
                              const BlockJobDriver *driver,
@@ -704,6 +711,7 @@ static void mirror_start_job(BlockDriverState *bs, 
BlockDriverState *target,
     s->granularity = granularity;
     s->buf_size = MAX(buf_size, granularity);
     s->unmap = unmap;
+    s->detect_zeroes = detect_zeroes;
 
     s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp);
     if (!s->dirty_bitmap) {
@@ -722,7 +730,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState 
*target,
                   int64_t speed, uint32_t granularity, int64_t buf_size,
                   MirrorSyncMode mode, BlockdevOnError on_source_error,
                   BlockdevOnError on_target_error,
-                  bool unmap,
+                  bool unmap, bool detect_zeroes,
                   BlockCompletionFunc *cb,
                   void *opaque, Error **errp)
 {
@@ -737,7 +745,8 @@ void mirror_start(BlockDriverState *bs, BlockDriverState 
*target,
     base = mode == MIRROR_SYNC_MODE_TOP ? bs->backing_hd : NULL;
     mirror_start_job(bs, target, replaces,
                      speed, granularity, buf_size,
-                     on_source_error, on_target_error, unmap, cb, opaque, errp,
+                     on_source_error, on_target_error, unmap,
+                     detect_zeroes, cb, opaque, errp,
                      &mirror_job_driver, is_none_mode, base);
 }
 
@@ -785,7 +794,7 @@ void commit_active_start(BlockDriverState *bs, 
BlockDriverState *base,
 
     bdrv_ref(base);
     mirror_start_job(bs, base, NULL, speed, 0, 0,
-                     on_error, on_error, false, cb, opaque, &local_err,
+                     on_error, on_error, false, false, cb, opaque, &local_err,
                      &commit_active_job_driver, false, base);
     if (local_err) {
         error_propagate(errp, local_err);
diff --git a/blockdev.c b/blockdev.c
index 4387e14..d86ec1c 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2633,6 +2633,7 @@ void qmp_drive_mirror(const char *device, const char 
*target,
                       bool has_on_source_error, BlockdevOnError 
on_source_error,
                       bool has_on_target_error, BlockdevOnError 
on_target_error,
                       bool has_unmap, bool unmap,
+                      bool has_detect_zeroes, bool detect_zeroes,
                       Error **errp)
 {
     BlockBackend *blk;
@@ -2667,6 +2668,9 @@ void qmp_drive_mirror(const char *device, const char 
*target,
     if (!has_unmap) {
         unmap = true;
     }
+    if (!has_detect_zeroes) {
+        detect_zeroes = true;
+    }
 
     if (granularity != 0 && (granularity < 512 || granularity > 1048576 * 64)) 
{
         error_set(errp, QERR_INVALID_PARAMETER_VALUE, "granularity",
@@ -2806,7 +2810,7 @@ void qmp_drive_mirror(const char *device, const char 
*target,
                  has_replaces ? replaces : NULL,
                  speed, granularity, buf_size, sync,
                  on_source_error, on_target_error,
-                 unmap,
+                 unmap, detect_zeroes,
                  block_job_cb, bs, &local_err);
     if (local_err != NULL) {
         bdrv_unref(target_bs);
diff --git a/hmp.c b/hmp.c
index 62c53e0..28a597f 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1056,7 +1056,7 @@ void hmp_drive_mirror(Monitor *mon, const QDict *qdict)
                      false, NULL, false, NULL,
                      full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
                      true, mode, false, 0, false, 0, false, 0,
-                     false, 0, false, 0, false, true, &err);
+                     false, 0, false, 0, false, true, false, true, &err);
     hmp_handle_error(mon, &err);
 }
 
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 459fe1c..10715a6 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -591,6 +591,7 @@ void commit_active_start(BlockDriverState *bs, 
BlockDriverState *base,
  * @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.
  * @unmap: Whether to unmap target where source sectors only contain zeroes.
+ * @detect_zero: Whether to do zero detect of source sectors.
  * @cb: Completion function for the job.
  * @opaque: Opaque pointer value passed to @cb.
  * @errp: Error object.
@@ -605,7 +606,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState 
*target,
                   int64_t speed, uint32_t granularity, int64_t buf_size,
                   MirrorSyncMode mode, BlockdevOnError on_source_error,
                   BlockdevOnError on_target_error,
-                  bool unmap,
+                  bool unmap, bool detect_zeroes,
                   BlockCompletionFunc *cb,
                   void *opaque, Error **errp);
 
diff --git a/qapi/block-core.json b/qapi/block-core.json
index a59063d..2014dc6 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -959,6 +959,8 @@
 #         target image sectors will be unmapped; otherwise, zeroes will be
 #         written. Both will result in identical contents.
 #         Default is true. (Since 2.4)
+# @detect-zeroes: #optional Whether to detect zero sectors in source and use
+#                 zero write on target. Default is true. (Since 2.4)
 #
 # Returns: nothing on success
 #          If @device is not a valid block device, DeviceNotFound
@@ -972,7 +974,7 @@
             '*speed': 'int', '*granularity': 'uint32',
             '*buf-size': 'int', '*on-source-error': 'BlockdevOnError',
             '*on-target-error': 'BlockdevOnError',
-            '*unmap': 'bool' } }
+            '*unmap': 'bool', '*detect-zeroes': 'bool' } }
 
 ##
 # @BlockDirtyBitmap
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 63c86fc..cac07fc 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1503,7 +1503,7 @@ EQMP
         .args_type  = "sync:s,device:B,target:s,speed:i?,mode:s?,format:s?,"
                       "node-name:s?,replaces:s?,"
                       "on-source-error:s?,on-target-error:s?,"
-                      "unmap:b?,"
+                      "unmap:b?,detect-zeroes:b?"
                       "granularity:i?,buf-size:i?",
         .mhandler.cmd_new = qmp_marshal_input_drive_mirror,
     },
@@ -1545,6 +1545,8 @@ Arguments:
   (BlockdevOnError, default 'report')
 - "unmap": whether the target sectors should be discarded where source has only
   zeroes. (json-bool, optional, default true)
+- "detect-zeroes": if true, the source sectors that are zeroes will be written 
as
+  sparse on target. (json-bool, optional, default true)
 
 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
-- 
2.4.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]