Patchwork [v2,16/17] qapi: Convert info snapshots

login
register
mail settings
Submitter Pavel Hrdina
Date Dec. 13, 2012, 3:40 p.m.
Message ID <48c8d2bceafe7f37a637912ddd98c648a8c3d0be.1355404685.git.phrdina@redhat.com>
Download mbox | patch
Permalink /patch/206128/
State New
Headers show

Comments

Pavel Hrdina - Dec. 13, 2012, 3:40 p.m.
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
 hmp.c            | 33 +++++++++++++++++++++++++++++++++
 hmp.h            |  1 +
 monitor.c        |  2 +-
 qapi-schema.json | 13 +++++++++++++
 qmp-commands.hx  | 34 ++++++++++++++++++++++++++++++++++
 savevm.c         | 52 +++++++++++++++++++++++++---------------------------
 sysemu.h         |  2 --
 7 files changed, 107 insertions(+), 30 deletions(-)
Luiz Capitulino - Dec. 14, 2012, 5:18 p.m.
On Thu, 13 Dec 2012 16:40:50 +0100
Pavel Hrdina <phrdina@redhat.com> wrote:

> Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
> ---
>  hmp.c            | 33 +++++++++++++++++++++++++++++++++
>  hmp.h            |  1 +
>  monitor.c        |  2 +-
>  qapi-schema.json | 13 +++++++++++++
>  qmp-commands.hx  | 34 ++++++++++++++++++++++++++++++++++
>  savevm.c         | 52 +++++++++++++++++++++++++---------------------------
>  sysemu.h         |  2 --
>  7 files changed, 107 insertions(+), 30 deletions(-)
> 
> diff --git a/hmp.c b/hmp.c
> index 78c9a7c..1983210 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -628,6 +628,39 @@ void hmp_info_block_jobs(Monitor *mon)
>      }
>  }
>  
> +void hmp_info_snapshots(Monitor *mon)
> +{
> +    SnapshotInfoList *list;
> +    Error *err = NULL;
> +    char buf[256];
> +    QEMUSnapshotInfo sn;
> +
> +    list = qmp_query_vm_snapshots(&err);
> +
> +    if (error_is_set(&err)) {
> +        hmp_handle_error(mon, &err);
> +        return;
> +    }
> +
> +    if (!list) {
> +        monitor_printf(mon, "There is no snapshot available.\n");
> +        return;
> +    }
> +    monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
> +    while (list) {
> +        memcpy(&(sn.id_str), list->value->id, sizeof(sn.id_str));
> +        memcpy(&(sn.name), list->value->name, sizeof(sn.name));
> +        sn.date_sec = list->value->date_sec;
> +        sn.date_nsec = list->value->date_nsec;
> +        sn.vm_clock_nsec = list->value->vm_clock_nsec;
> +        sn.vm_state_size = list->value->vm_state_size;
> +        monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), &sn));
> +        list = list->next;
> +    }
> +
> +    qapi_free_SnapshotInfoList(list);

list should be NULL here, so you're actually leaking the list returned
by qmp_query_vm_snapshots().

> +}
> +
>  void hmp_quit(Monitor *mon, const QDict *qdict)
>  {
>      monitor_suspend(mon);
> diff --git a/hmp.h b/hmp.h
> index 8f929af..1c21a82 100644
> --- a/hmp.h
> +++ b/hmp.h
> @@ -36,6 +36,7 @@ void hmp_info_spice(Monitor *mon);
>  void hmp_info_balloon(Monitor *mon);
>  void hmp_info_pci(Monitor *mon);
>  void hmp_info_block_jobs(Monitor *mon);
> +void hmp_info_snapshots(Monitor *mon);
>  void hmp_quit(Monitor *mon, const QDict *qdict);
>  void hmp_stop(Monitor *mon, const QDict *qdict);
>  void hmp_system_reset(Monitor *mon, const QDict *qdict);
> diff --git a/monitor.c b/monitor.c
> index b8abff2..2be93c0 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -2596,7 +2596,7 @@ static mon_cmd_t info_cmds[] = {
>          .args_type  = "",
>          .params     = "",
>          .help       = "show the currently saved VM snapshots",
> -        .mhandler.info = do_info_snapshots,
> +        .mhandler.info = hmp_info_snapshots,
>      },
>      {
>          .name       = "status",
> diff --git a/qapi-schema.json b/qapi-schema.json
> index 431df69..a8742a1 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -1224,6 +1224,19 @@
>  { 'command': 'query-block-jobs', 'returns': ['BlockJobInfo'] }
>  
>  ##
> +# @query-vm-snapshots:
> +#
> +# List available snapshots for VM.
> +#
> +# Returns: an array of @SnapshotInfo describing each snapshot or an empty array
> +#            on success
> +#          If an error occurs, GenericError with error message

We don't need the line above.

> +#
> +# Since: 1.3
> +##
> +{ 'command': 'query-vm-snapshots', 'returns': ['SnapshotInfo'] }
> +
> +##
>  # @quit:
>  #
>  # This command will cause the QEMU process to exit gracefully.  While every
> diff --git a/qmp-commands.hx b/qmp-commands.hx
> index c3671f7..f839c40 100644
> --- a/qmp-commands.hx
> +++ b/qmp-commands.hx
> @@ -2732,3 +2732,37 @@ EQMP
>          .args_type  = "",
>          .mhandler.cmd_new = qmp_marshal_input_query_target,
>      },
> +
> +SQMP
> +query-vm-snapshots
> +----------
> +
> +List available snapshots for VM.
> +
> +Return an array of json-object, each with the following information:
> +
> +- "id": unique snapshot id
> +
> +- "name": user choosen name
> +
> +- "vm-state-size": size of the VM state
> +
> +- "date-sec": UTC date of the snapshot
> +
> +- "date-nsec": date in nano seconds
> +
> +- "vm-clock-nsec": VM clock relative to boot in nano seconds
> +
> +Example:
> +
> +-> { "execute": "query-vm-snapshots" }
> +<- {"return": [{"vm-clock-nsec": 36420253254, "name": "my_snapshot",
> +                "date-sec": 1345120008, "date-nsec": 151984000, "id": "6",
> +                "vm-state-size": 166515500}]}
> +
> +EQMP
> +    {
> +        .name       = "query-vm-snapshots",
> +        .args_type  = "",
> +        .mhandler.cmd_new = qmp_marshal_input_query_vm_snapshots,
> +    },
> diff --git a/savevm.c b/savevm.c
> index 8da888e..36ccc46 100644
> --- a/savevm.c
> +++ b/savevm.c
> @@ -2373,34 +2373,28 @@ void qmp_vm_snapshot_delete(const char *name, Error **errp)
>      }
>  }
>  
> -void do_info_snapshots(Monitor *mon)
> +SnapshotInfoList *qmp_query_vm_snapshots(Error **errp)
>  {
> +    SnapshotInfoList *snapshot_list = NULL, *last = NULL;
>      BlockDriverState *bs, *bs1;
>      QEMUSnapshotInfo *sn_tab, *sn, s, *sn_info = &s;
>      int nb_sns, i, ret, available;
> -    int total;
> -    int *available_snapshots;
> -    char buf[256];
>  
>      bs = bdrv_snapshots();
>      if (!bs) {
> -        monitor_printf(mon, "No available block device supports snapshots\n");
> -        return;
> +        error_setg(errp, "No block device supports snapshots.");
> +        return NULL;
>      }
>  
> -    nb_sns = bdrv_snapshot_list(bs, &sn_tab, NULL);
> -    if (nb_sns < 0) {
> -        monitor_printf(mon, "bdrv_snapshot_list: error %d\n", nb_sns);
> -        return;
> +    nb_sns = bdrv_snapshot_list(bs, &sn_tab, errp);

You should not use errp to detect internal errors.

> +    if (error_is_set(errp)) {
> +        return NULL;
>      }
>  
>      if (nb_sns == 0) {
> -        monitor_printf(mon, "There is no snapshot available.\n");
> -        return;
> +        return NULL;
>      }
>  
> -    available_snapshots = g_malloc0(sizeof(int) * nb_sns);
> -    total = 0;
>      for (i = 0; i < nb_sns; i++) {
>          sn = &sn_tab[i];
>          available = 1;
> @@ -2417,24 +2411,28 @@ void do_info_snapshots(Monitor *mon)
>          }
>  
>          if (available) {
> -            available_snapshots[total] = i;
> -            total++;
> -        }
> -    }
> -
> -    if (total > 0) {
> -        monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
> -        for (i = 0; i < total; i++) {
> -            sn = &sn_tab[available_snapshots[i]];
> -            monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
> +            SnapshotInfoList *info = g_malloc0(sizeof(*info));
> +            info->value = g_malloc0(sizeof(*info->value));
> +            info->value->id = g_strdup(sn->id_str);
> +            info->value->name = g_strdup(sn->name);
> +            info->value->vm_state_size = sn->vm_state_size;
> +            info->value->date_sec = sn->date_sec;
> +            info->value->date_nsec = sn->date_nsec;
> +            info->value->vm_clock_nsec = sn->vm_clock_nsec;
> +
> +            if (!snapshot_list) {
> +                snapshot_list = info;
> +                last = info;
> +            } else {
> +                last->next = info;
> +                last = info;
> +            }
>          }
> -    } else {
> -        monitor_printf(mon, "There is no suitable snapshot available\n");
>      }
>  
>      g_free(sn_tab);
> -    g_free(available_snapshots);
>  
> +    return snapshot_list;
>  }
>  
>  void vmstate_register_ram(MemoryRegion *mr, DeviceState *dev)
> diff --git a/sysemu.h b/sysemu.h
> index e440dcc..e7182f4 100644
> --- a/sysemu.h
> +++ b/sysemu.h
> @@ -65,8 +65,6 @@ void qemu_remove_exit_notifier(Notifier *notify);
>  
>  void qemu_add_machine_init_done_notifier(Notifier *notify);
>  
> -void do_info_snapshots(Monitor *mon);
> -
>  void qemu_announce_self(void);
>  
>  bool qemu_savevm_state_blocked(Error **errp);

Patch

diff --git a/hmp.c b/hmp.c
index 78c9a7c..1983210 100644
--- a/hmp.c
+++ b/hmp.c
@@ -628,6 +628,39 @@  void hmp_info_block_jobs(Monitor *mon)
     }
 }
 
+void hmp_info_snapshots(Monitor *mon)
+{
+    SnapshotInfoList *list;
+    Error *err = NULL;
+    char buf[256];
+    QEMUSnapshotInfo sn;
+
+    list = qmp_query_vm_snapshots(&err);
+
+    if (error_is_set(&err)) {
+        hmp_handle_error(mon, &err);
+        return;
+    }
+
+    if (!list) {
+        monitor_printf(mon, "There is no snapshot available.\n");
+        return;
+    }
+    monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
+    while (list) {
+        memcpy(&(sn.id_str), list->value->id, sizeof(sn.id_str));
+        memcpy(&(sn.name), list->value->name, sizeof(sn.name));
+        sn.date_sec = list->value->date_sec;
+        sn.date_nsec = list->value->date_nsec;
+        sn.vm_clock_nsec = list->value->vm_clock_nsec;
+        sn.vm_state_size = list->value->vm_state_size;
+        monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), &sn));
+        list = list->next;
+    }
+
+    qapi_free_SnapshotInfoList(list);
+}
+
 void hmp_quit(Monitor *mon, const QDict *qdict)
 {
     monitor_suspend(mon);
diff --git a/hmp.h b/hmp.h
index 8f929af..1c21a82 100644
--- a/hmp.h
+++ b/hmp.h
@@ -36,6 +36,7 @@  void hmp_info_spice(Monitor *mon);
 void hmp_info_balloon(Monitor *mon);
 void hmp_info_pci(Monitor *mon);
 void hmp_info_block_jobs(Monitor *mon);
+void hmp_info_snapshots(Monitor *mon);
 void hmp_quit(Monitor *mon, const QDict *qdict);
 void hmp_stop(Monitor *mon, const QDict *qdict);
 void hmp_system_reset(Monitor *mon, const QDict *qdict);
diff --git a/monitor.c b/monitor.c
index b8abff2..2be93c0 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2596,7 +2596,7 @@  static mon_cmd_t info_cmds[] = {
         .args_type  = "",
         .params     = "",
         .help       = "show the currently saved VM snapshots",
-        .mhandler.info = do_info_snapshots,
+        .mhandler.info = hmp_info_snapshots,
     },
     {
         .name       = "status",
diff --git a/qapi-schema.json b/qapi-schema.json
index 431df69..a8742a1 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1224,6 +1224,19 @@ 
 { 'command': 'query-block-jobs', 'returns': ['BlockJobInfo'] }
 
 ##
+# @query-vm-snapshots:
+#
+# List available snapshots for VM.
+#
+# Returns: an array of @SnapshotInfo describing each snapshot or an empty array
+#            on success
+#          If an error occurs, GenericError with error message
+#
+# Since: 1.3
+##
+{ 'command': 'query-vm-snapshots', 'returns': ['SnapshotInfo'] }
+
+##
 # @quit:
 #
 # This command will cause the QEMU process to exit gracefully.  While every
diff --git a/qmp-commands.hx b/qmp-commands.hx
index c3671f7..f839c40 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2732,3 +2732,37 @@  EQMP
         .args_type  = "",
         .mhandler.cmd_new = qmp_marshal_input_query_target,
     },
+
+SQMP
+query-vm-snapshots
+----------
+
+List available snapshots for VM.
+
+Return an array of json-object, each with the following information:
+
+- "id": unique snapshot id
+
+- "name": user choosen name
+
+- "vm-state-size": size of the VM state
+
+- "date-sec": UTC date of the snapshot
+
+- "date-nsec": date in nano seconds
+
+- "vm-clock-nsec": VM clock relative to boot in nano seconds
+
+Example:
+
+-> { "execute": "query-vm-snapshots" }
+<- {"return": [{"vm-clock-nsec": 36420253254, "name": "my_snapshot",
+                "date-sec": 1345120008, "date-nsec": 151984000, "id": "6",
+                "vm-state-size": 166515500}]}
+
+EQMP
+    {
+        .name       = "query-vm-snapshots",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_vm_snapshots,
+    },
diff --git a/savevm.c b/savevm.c
index 8da888e..36ccc46 100644
--- a/savevm.c
+++ b/savevm.c
@@ -2373,34 +2373,28 @@  void qmp_vm_snapshot_delete(const char *name, Error **errp)
     }
 }
 
-void do_info_snapshots(Monitor *mon)
+SnapshotInfoList *qmp_query_vm_snapshots(Error **errp)
 {
+    SnapshotInfoList *snapshot_list = NULL, *last = NULL;
     BlockDriverState *bs, *bs1;
     QEMUSnapshotInfo *sn_tab, *sn, s, *sn_info = &s;
     int nb_sns, i, ret, available;
-    int total;
-    int *available_snapshots;
-    char buf[256];
 
     bs = bdrv_snapshots();
     if (!bs) {
-        monitor_printf(mon, "No available block device supports snapshots\n");
-        return;
+        error_setg(errp, "No block device supports snapshots.");
+        return NULL;
     }
 
-    nb_sns = bdrv_snapshot_list(bs, &sn_tab, NULL);
-    if (nb_sns < 0) {
-        monitor_printf(mon, "bdrv_snapshot_list: error %d\n", nb_sns);
-        return;
+    nb_sns = bdrv_snapshot_list(bs, &sn_tab, errp);
+    if (error_is_set(errp)) {
+        return NULL;
     }
 
     if (nb_sns == 0) {
-        monitor_printf(mon, "There is no snapshot available.\n");
-        return;
+        return NULL;
     }
 
-    available_snapshots = g_malloc0(sizeof(int) * nb_sns);
-    total = 0;
     for (i = 0; i < nb_sns; i++) {
         sn = &sn_tab[i];
         available = 1;
@@ -2417,24 +2411,28 @@  void do_info_snapshots(Monitor *mon)
         }
 
         if (available) {
-            available_snapshots[total] = i;
-            total++;
-        }
-    }
-
-    if (total > 0) {
-        monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
-        for (i = 0; i < total; i++) {
-            sn = &sn_tab[available_snapshots[i]];
-            monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
+            SnapshotInfoList *info = g_malloc0(sizeof(*info));
+            info->value = g_malloc0(sizeof(*info->value));
+            info->value->id = g_strdup(sn->id_str);
+            info->value->name = g_strdup(sn->name);
+            info->value->vm_state_size = sn->vm_state_size;
+            info->value->date_sec = sn->date_sec;
+            info->value->date_nsec = sn->date_nsec;
+            info->value->vm_clock_nsec = sn->vm_clock_nsec;
+
+            if (!snapshot_list) {
+                snapshot_list = info;
+                last = info;
+            } else {
+                last->next = info;
+                last = info;
+            }
         }
-    } else {
-        monitor_printf(mon, "There is no suitable snapshot available\n");
     }
 
     g_free(sn_tab);
-    g_free(available_snapshots);
 
+    return snapshot_list;
 }
 
 void vmstate_register_ram(MemoryRegion *mr, DeviceState *dev)
diff --git a/sysemu.h b/sysemu.h
index e440dcc..e7182f4 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -65,8 +65,6 @@  void qemu_remove_exit_notifier(Notifier *notify);
 
 void qemu_add_machine_init_done_notifier(Notifier *notify);
 
-void do_info_snapshots(Monitor *mon);
-
 void qemu_announce_self(void);
 
 bool qemu_savevm_state_blocked(Error **errp);