On Thu, 13 Dec 2012 16:40:50 +0100 Pavel Hrdina <phrd...@redhat.com> wrote:
> Signed-off-by: Pavel Hrdina <phrd...@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);