Patchwork [V7,11/14] qmp: add interface query-snapshots

login
register
mail settings
Submitter Wayne Xia
Date Feb. 26, 2013, 10:40 a.m.
Message ID <1361875228-15769-12-git-send-email-xiawenc@linux.vnet.ibm.com>
Download mbox | patch
Permalink /patch/223216/
State New
Headers show

Comments

Wayne Xia - Feb. 26, 2013, 10:40 a.m.
This interface now return valid internal snapshots for whole vm.
  Note that filter use bdrv_can_read_snapshot() instead of
bdrv_can_snapshot(), which should be the correct behavior in information
retrieving funtion.

Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
---
 block.c          |   32 ++++++++++++++++++++++++++++++++
 qapi-schema.json |   14 ++++++++++++++
 qmp-commands.hx  |   53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 99 insertions(+), 0 deletions(-)
Markus Armbruster - Feb. 27, 2013, 4:08 p.m.
Wenchao Xia <xiawenc@linux.vnet.ibm.com> writes:

>   This interface now return valid internal snapshots for whole vm.
>   Note that filter use bdrv_can_read_snapshot() instead of
> bdrv_can_snapshot(), which should be the correct behavior in information
> retrieving funtion.

This is just like query-images, except it's for the system as a whole
rather than individual block devices.  Correct?
Wayne Xia - Feb. 28, 2013, 2:14 a.m.
于 2013-2-28 0:08, Markus Armbruster 写道:
> Wenchao Xia <xiawenc@linux.vnet.ibm.com> writes:
> 
>>    This interface now return valid internal snapshots for whole vm.
>>    Note that filter use bdrv_can_read_snapshot() instead of
>> bdrv_can_snapshot(), which should be the correct behavior in information
>> retrieving funtion.
> 
> This is just like query-images, except it's for the system as a whole
> rather than individual block devices.  Correct?
> 
  Yes, just for snapshot info for whole vm.
Eric Blake - Feb. 28, 2013, 2:55 a.m.
On 02/27/2013 07:14 PM, Wenchao Xia wrote:
> 于 2013-2-28 0:08, Markus Armbruster 写道:
>> Wenchao Xia <xiawenc@linux.vnet.ibm.com> writes:
>>
>>>    This interface now return valid internal snapshots for whole vm.
>>>    Note that filter use bdrv_can_read_snapshot() instead of
>>> bdrv_can_snapshot(), which should be the correct behavior in information
>>> retrieving funtion.
>>
>> This is just like query-images, except it's for the system as a whole
>> rather than individual block devices.  Correct?
>>
>   Yes, just for snapshot info for whole vm.

Another way of looking at it: if a guest has two images, a.qcow and
b.qcow, where a.qcow includes snapshot id '1' named 'bar', and id '2'
named 'baz'; and where b.qcow includes snapshot id '1' named 'foo', and
id '2' named 'bar', then querying individual block devices will see both
internal snapshots of each device, but querying the system as a whole
will see only a single snapshot named 'bar' and with no reliable id.
This is because the 'loadvm' HMP command (or whatever equivalent we
finally ever make in QMP) needs to act on all devices at once; reverting
to id '1' or name 'foo' doesn't make much sense, because those are not
consistent.  A management app might be able to piece things together
through a more complicated disk-at-a-time transaction, at a lower level
than what 'loadvm' does.  But this command seems useful for stating what
snapshots are consistent enough for 'loadvm' to have a chance of succeeding.

Patch

diff --git a/block.c b/block.c
index dd2259a..6bda890 100644
--- a/block.c
+++ b/block.c
@@ -2880,6 +2880,38 @@  SnapshotInfoList *bdrv_query_snapshot_infolist(BlockDriverState *bs,
     return head;
 }
 
+/* check if sn exist on all block devices, 0 means valid */
+static int snapshot_filter_vm(const QEMUSnapshotInfo *sn, void *opaque)
+{
+    BlockDriverState *bs = (BlockDriverState *)opaque, *bs1 = NULL;
+    QEMUSnapshotInfo s, *sn_info = &s;
+    int ret = 0;
+
+    while ((bs1 = bdrv_next(bs1))) {
+        if (bdrv_can_read_snapshot(bs1) && bs1 != bs) {
+            ret = bdrv_snapshot_find(bs1, sn_info, sn->id_str, NULL);
+            if (ret < 0) {
+                ret = -1;
+                break;
+            }
+        }
+    }
+    return ret;
+}
+
+SnapshotInfoList *qmp_query_snapshots(Error **errp)
+{
+    BlockDriverState *bs;
+
+    /* internal snapshot for whole vm */
+    bs = bdrv_snapshots();
+    if (!bs) {
+        error_setg(errp, "No available block device supports snapshots\n");
+        return NULL;
+    }
+    return bdrv_query_snapshot_infolist(bs, snapshot_filter_vm, bs, errp);
+}
+
 /* collect all internal snapshot info in a image for ImageInfo */
 static void collect_snapshots_info(BlockDriverState *bs,
                                    ImageInfo *info,
diff --git a/qapi-schema.json b/qapi-schema.json
index 9122bb9..8a9a052 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -823,6 +823,20 @@ 
   'returns': ['DeviceImageInfo'] }
 
 ##
+# @query-snapshots:
+#
+# Get a list of internal snapshots for whole virtual machine, only valid
+# internal snapshot will be returned, inconsistent ones will be ignored.
+#
+# Returns: a list of @SnapshotInfo describing all consistent virtual machine
+#          snapshots
+#
+# Since: 1.5
+##
+{ 'command': 'query-snapshots',
+  'returns': ['SnapshotInfo'] }
+
+##
 # @BlockDeviceStats:
 #
 # Statistics of a virtual block device or a block backing device.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 292d61e..3a5f9bb 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1819,6 +1819,59 @@  EQMP
     },
 
 SQMP
+query-snapshots
+-----------
+
+Show the internal consistent snapshot information.
+
+Each snapshot information is stored in a json-object and the returned value
+is a json-array of all snapshots.
+
+Each json-object contain the following:
+
+- "id": unique snapshot id (json-string)
+- "name": internal snapshot name (json-string)
+- "vm-state-size": size of the VM state in bytes (json-int)
+- "date-sec": UTC date of the snapshot in seconds (json-int)
+- "date-nsec": fractional part in nano seconds to be used with date-sec(json-int)
+- "vm-clock-sec": VM clock relative to boot in seconds (json-int)
+- "vm-clock-nsec": fractional part in nano seconds to be used with vm-clock-sec (json-int)
+
+Example:
+
+-> { "execute": "query-snapshots" }
+<- {
+      "return":[
+         {
+            "id": "1",
+            "name": "snapshot1",
+            "vm-state-size": 0,
+            "date-sec": 10000200,
+            "date-nsec": 12,
+            "vm-clock-sec": 206,
+            "vm-clock-nsec": 30
+         },
+         {
+            "id": "2",
+            "name": "snapshot2",
+            "vm-state-size": 34000000,
+            "date-sec": 13000200,
+            "date-nsec": 32,
+            "vm-clock-sec": 406,
+            "vm-clock-nsec": 31
+         }
+      ]
+   }
+
+EQMP
+
+    {
+        .name       = "query-snapshots",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_snapshots,
+    },
+
+SQMP
 query-blockstats
 ----------------