qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [RFC PATCH 4/4] QAPI: add command for live block commit, 'b


From: Jeff Cody
Subject: [Qemu-devel] [RFC PATCH 4/4] QAPI: add command for live block commit, 'block-commit'
Date: Tue, 31 Jul 2012 01:16:13 -0400

The command for live block commit is added, which has the following
arguments:

device: the block device to perform the commit on (mandatory)
base:   the base image to commit into; optional (if not specified,
        it is the underlying original image)
top:    the top image of the commit - all data from inside top down
        to base will be committed into base. optional (if not specified,
        it is the active image) - see note below
speed:  maximum speed, in bytes/sec
on_error: action to take on error (optional - default is report)

note: eventually this will support merging down the active layer,
      but that code is not yet complete.  If the active layer is passed
      in currently as top, or top is left to the default, then the error
      QERR_TOP_NOT_FOUND will be returned.

The is down as a block job, so upon completion a BLOCK_JOB_COMPLETED will
be emitted.

Signed-off-by: Jeff Cody <address@hidden>
---
 blockdev.c       |   78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 qapi-schema.json |   33 +++++++++++++++++++++++
 qmp-commands.hx  |    6 +++++
 3 files changed, 117 insertions(+)

diff --git a/blockdev.c b/blockdev.c
index f39d301..a61ee38 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -831,6 +831,84 @@ exit:
     return;
 }
 
+void qmp_block_commit(const char *device,
+                      bool has_base, const char *base,
+                      bool has_top, const char *top,
+                      bool has_speed, int64_t speed,
+                      bool has_on_error, BlockdevOnError on_error,
+                      Error **errp)
+{
+    BlockDriverState *bs;
+    BlockDriverState *base_bs, *top_bs;
+    Error *local_err = NULL;
+    int orig_base_flags, orig_top_flags;
+
+    if (!has_on_error) {
+        on_error = BLOCKDEV_ON_ERROR_REPORT;
+    }
+
+    /* drain all i/o before commits */
+    bdrv_drain_all();
+
+
+    bs = bdrv_find(device);
+    if (!bs) {
+        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+        return;
+    }
+    if (base && has_base) {
+        base_bs = bdrv_find_backing_image(bs, base);
+        if (base_bs == NULL) {
+            error_set(errp, QERR_BASE_NOT_FOUND, base);
+            return;
+        }
+    } else {
+        base_bs = bdrv_find_base(bs);
+        if (base_bs == NULL) {
+            error_set(errp, QERR_BASE_NOT_FOUND, "NULL");
+            return;
+        }
+    }
+
+    if (top && has_top) {
+        /* if we want to allow the active layer,
+         * use 'bdrv_find_image()' here */
+        top_bs = bdrv_find_backing_image(bs, top);
+        if (top_bs == NULL) {
+            error_set(errp, QERR_TOP_NOT_FOUND, top);
+            return;
+        }
+    } else {
+        top_bs = bs;
+    }
+
+    orig_base_flags = bdrv_get_flags(base_bs);
+    /* convert base_bs to r/w, if necessary */
+    if (!(orig_base_flags & BDRV_O_RDWR)) {
+        bdrv_reopen(base_bs, orig_base_flags | BDRV_O_RDWR);
+    }
+
+    /* need to also make top r/w, so that when the commit is
+     * finished we can change the backing file */
+    orig_top_flags = bdrv_get_flags(top_bs);
+    /* convert top_bs to r/w, if necessary */
+    if (!(orig_top_flags & BDRV_O_RDWR)) {
+        bdrv_reopen(top_bs, orig_top_flags | BDRV_O_RDWR);
+    }
+
+    commit_start(bs, base_bs, top_bs, speed, on_error,
+                 block_job_cb, bs, orig_base_flags, orig_top_flags,
+                 &local_err);
+    if (local_err != NULL) {
+        error_propagate(errp, local_err);
+        return;
+    }
+    /* Grab a reference so hotplug does not delete the BlockDriverState from
+     * underneath us.
+     */
+    drive_get_ref(drive_get_by_blockdev(bs));
+}
+
 void qmp_drive_mirror(const char *device, const char *target,
                       bool has_format, const char *format,
                       enum MirrorSyncMode sync,
diff --git a/qapi-schema.json b/qapi-schema.json
index db6903f..9ab6f90 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1365,6 +1365,39 @@
   'returns': 'str' } 
 
 ##
+# @block-commit
+#
+# Live commit of data from child image nodes into parent nodes - i.e.,
+# writes data between 'top' and 'base' into 'base'.
+#
+# @device:  the name of the device
+#
+# @base:   #optional The parent image of the device to write data into.
+#                    If not specified, this is the original parent image.
+#
+# @top:    #optional The child image, above which data will not be commited
+#                    down.  If not specified, this is the active layer.
+#
+# @speed:  #optional the maximum speed, in bytes per second
+#
+# @on_error: #optional the action to take on an error (default report)
+#
+# Returns: Nothing on success
+#          If commit or stream is already active on this device, DeviceInUse
+#          If @device does not exist, DeviceNotFound
+#          If image commit is not supported by this device, NotSupported
+#          If @base does not exist, BaseNotFound
+#          If @top does not exist, TopNotFound
+#          If @speed is invalid, InvalidParameter
+#
+# Since: 1.2
+#
+##
+{ 'command': 'block-commit',
+  'data': { 'device': 'str', '*base': 'str', '*top': 'str',
+            '*speed': 'int', '*on_error': 'BlockdevOnError' } }
+
+##
 # @drive-mirror
 #
 # Start mirroring a block device's writes to a new destination.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index bde96cf..2f21142 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -723,6 +723,12 @@ EQMP
     },
 
     {
+        .name       = "block-commit",
+        .args_type  = "device:B,base:s?,top:s?,speed:o?,on_error:s?",
+        .mhandler.cmd_new = qmp_marshal_input_block_commit,
+    },
+
+    {
         .name       = "block-job-set-speed",
         .args_type  = "device:B,speed:o",
         .mhandler.cmd_new = qmp_marshal_input_block_job_set_speed,
-- 
1.7.10.4




reply via email to

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