All of lore.kernel.org
 help / color / mirror / Atom feed
From: Markus Armbruster <armbru@redhat.com>
To: Pavel Hrdina <phrdina@redhat.com>
Cc: qemu-devel@nongnu.org, lcapitulino@redhat.com
Subject: Re: [Qemu-devel] [PATCH v4 07/11] qapi: Convert savevm
Date: Tue, 09 Apr 2013 18:04:18 +0200	[thread overview]
Message-ID: <87d2u3667x.fsf@blackfin.pond.sub.org> (raw)
In-Reply-To: <e15048016ebe0f9f30310d129933f29649a94e42.1364565637.git.phrdina@redhat.com> (Pavel Hrdina's message of "Fri, 29 Mar 2013 15:12:34 +0100")

Patch no longer applies.

Pavel Hrdina <phrdina@redhat.com> writes:

> QMP command "vm-snapshot-save" has also extra optional force parameter
> to specify whether replace existing snapshot or not. It also returns
> information about created snapshot.

Took me a minute to realize that you're comparing it to HMP command
savevm.

> Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
> ---
>  hmp-commands.hx         |  4 ++--
>  hmp.c                   | 11 +++++++++
>  hmp.h                   |  1 +
>  include/sysemu/sysemu.h |  1 -
>  qapi-schema.json        | 22 ++++++++++++++++++
>  qmp-commands.hx         | 43 ++++++++++++++++++++++++++++++++++
>  savevm.c                | 62 +++++++++++++++++++++++++++++++------------------
>  7 files changed, 118 insertions(+), 26 deletions(-)
>
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index 3d98604..382b87d 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -310,7 +310,7 @@ ETEXI
>          .args_type  = "name:s?",
>          .params     = "[tag|id]",
>          .help       = "save a VM snapshot. If no tag or id are provided, a new snapshot is created",
> -        .mhandler.cmd = do_savevm,
> +        .mhandler.cmd = hmp_vm_snapshot_save,
>      },
>  
>  STEXI
> @@ -318,7 +318,7 @@ STEXI
>  @findex savevm
>  Create a snapshot of the whole virtual machine. If @var{tag} is
>  provided, it is used as human readable identifier. If there is already
> -a snapshot with the same tag or ID, it is replaced. More info at
> +a snapshot with the same @var{tag} or @var{id}, it is replaced. More info at
>  @ref{vm_snapshots}.
>  ETEXI
>  

Markup fix squashed in.  Acceptable, because it's really minor.

> diff --git a/hmp.c b/hmp.c
> index dbe9b90..b38b6ce 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -1433,3 +1433,14 @@ void hmp_chardev_remove(Monitor *mon, const QDict *qdict)
>      qmp_chardev_remove(qdict_get_str(qdict, "id"), &local_err);
>      hmp_handle_error(mon, &local_err);
>  }
> +
> +void hmp_vm_snapshot_save(Monitor *mon, const QDict *qdict)
> +{
> +    const char *name = qdict_get_try_str(qdict, "name");
> +    Error *err = NULL;
> +    SnapshotInfo *info = NULL;
> +
> +    info = qmp_vm_snapshot_save(!!name, name, true, true, &err);
> +    qapi_free_SnapshotInfo(info);
> +    hmp_handle_error(mon, &err);
> +}
> diff --git a/hmp.h b/hmp.h
> index 80e8b41..1bb8590 100644
> --- a/hmp.h
> +++ b/hmp.h
> @@ -86,5 +86,6 @@ void hmp_nbd_server_add(Monitor *mon, const QDict *qdict);
>  void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict);
>  void hmp_chardev_add(Monitor *mon, const QDict *qdict);
>  void hmp_chardev_remove(Monitor *mon, const QDict *qdict);
> +void hmp_vm_snapshot_save(Monitor *mon, const QDict *qdict);
>  
>  #endif
> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
> index 9e6a4a9..87b82d7 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -65,7 +65,6 @@ void qemu_remove_exit_notifier(Notifier *notify);
>  
>  void qemu_add_machine_init_done_notifier(Notifier *notify);
>  
> -void do_savevm(Monitor *mon, const QDict *qdict);
>  int load_vmstate(const char *name);
>  void do_delvm(Monitor *mon, const QDict *qdict);
>  void do_info_snapshots(Monitor *mon, const QDict *qdict);
> diff --git a/qapi-schema.json b/qapi-schema.json
> index f629a24..cbb73d9 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -3453,3 +3453,25 @@
>  # Since: 1.5
>  ##
>  { 'command': 'query-tpm', 'returns': ['TPMInfo'] }
> +
> +##
> +# @vm-snapshot-save:
> +#
> +# Create a snapshot of the whole virtual machine. If tag is provided as @name,
> +# it is used as human readable identifier. If there is already a snapshot
> +# with the same tag or id, the force argument needs to be true to replace it.

"tag or id"?

HMP command savevm's argument is matched against both QEMUSnapshotInfo
member id_str (a.k.a. id) and name (a.k.a. tag).  Do we really want that
kind of overloading in QMP?  Shouldn't we make it tag vs. id explicit
there?

> +#
> +# The VM is automatically stopped and resumed and saving a snapshot can take
> +# a long time.
> +#
> +# @name: #optional tag of new snapshot or tag|id of existing snapshot

Should we make this mandatory?  We have to keep the argument optional in
HMP, but that needn't concern us here.

> +#
> +# @force: #optional specify whether existing snapshot is replaced or not,
> +#         default is false
> +#
> +# Returns: SnapshotInfo on success
> +#
> +# Since: 1.5
> +##
> +{ 'command': 'vm-snapshot-save', 'data': {'*name': 'str', '*force': 'bool'},
> +  'returns': 'SnapshotInfo' }
> diff --git a/qmp-commands.hx b/qmp-commands.hx
> index 1e0e11e..119e7a5 100644
> --- a/qmp-commands.hx
> +++ b/qmp-commands.hx
> @@ -1445,6 +1445,49 @@ Example:
>  
>  EQMP
>      {
> +        .name       = "vm-snapshot-save",
> +        .args_type  = "name:s?,force:b?",
> +        .params     = "[name] [force]",
> +        .help       = "save a VM snapshot, to replace existing snapshot use force parameter",
> +        .mhandler.cmd_new = qmp_marshal_input_vm_snapshot_save
> +    },
> +
> +SQMP
> +vm-snapshot-save
> +------
> +
> +Create a snapshot of the whole virtual machine. If tag is provided as name,
> +it is used as human readable identifier. If there is already a snapshot with
> +the same tag, the force argument needs to be true to replace it.
> +
> +The VM is automatically stopped and resumed and saving a snapshot can take
> +a long time.
> +
> +Arguments:
> +
> +- "name": tag of new snapshot or tag|id of existing snapshot
> +          (json-string, optional)
> +
> +- "force": specify whether existing snapshot is replaced or not,
> +           default is false (json-bool, optional)
> +
> +Example:
> +
> +-> { "execute": "vm-snapshot-save", "arguments": { "name": "my_snapshot" } }
> +<- {
> +      "return": {
> +         "id": "1",
> +         "name": "my_snapshot",
> +         "date-sec": 1364480534,
> +         "date-nsec": 978215000,
> +         "vm-clock-sec": 5,
> +         "vm-clock-nsec": 153620449,
> +         "vm-state-size": 5709953
> +      }
> +   }
> +
> +EQMP
> +    {
>          .name       = "qmp_capabilities",
>          .args_type  = "",
>          .params     = "",
> diff --git a/savevm.c b/savevm.c
> index 3c1ac9e..7b127eb 100644
> --- a/savevm.c
> +++ b/savevm.c
> @@ -2249,17 +2249,18 @@ static int del_existing_snapshots(const char *name, Error **errp)
>      return 0;
>  }
>  
> -void do_savevm(Monitor *mon, const QDict *qdict)
> +SnapshotInfo *qmp_vm_snapshot_save(bool has_name, const char *name,
> +                                   bool has_force, bool force, Error **errp)
>  {
>      BlockDriverState *bs, *bs1;
>      QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
> +    SnapshotInfo *info = NULL;
>      int ret;
>      QEMUFile *f;
>      int saved_vm_running;
>      uint64_t vm_state_size;
>      qemu_timeval tv;
>      struct tm tm;
> -    const char *name = qdict_get_try_str(qdict, "name");
>      Error *local_err = NULL;
>  
>      /* Verify if there is a device that doesn't support snapshots and is writable */
> @@ -2271,16 +2272,16 @@ void do_savevm(Monitor *mon, const QDict *qdict)
>          }
>  
>          if (!bdrv_can_snapshot(bs)) {
> -            monitor_printf(mon, "Device '%s' is writable but does not support snapshots.\n",
> -                               bdrv_get_device_name(bs));
> -            return;
> +            error_setg(errp, "device '%s' is writable but does not support "
> +                       "snapshots", bdrv_get_device_name(bs));
> +            return NULL;

Any particular reason for de-capitalizing "Device"?  More of the same below.

>          }
>      }
>  
>      bs = bdrv_snapshots();
>      if (!bs) {
> -        monitor_printf(mon, "No block device can accept snapshots\n");
> -        return;
> +        error_setg(errp, "no block device can accept snapshots");
> +        return NULL;
>      }
>  
>      saved_vm_running = runstate_is_running();
> @@ -2294,11 +2295,23 @@ void do_savevm(Monitor *mon, const QDict *qdict)
>      sn->date_nsec = tv.tv_usec * 1000;
>      sn->vm_clock_nsec = qemu_get_clock_ns(vm_clock);
>  
> -    if (name) {
> +    if (has_name) {
>          ret = bdrv_snapshot_find(bs, old_sn, name);
>          if (ret >= 0) {
> -            pstrcpy(sn->name, sizeof(sn->name), old_sn->name);
> -            pstrcpy(sn->id_str, sizeof(sn->id_str), old_sn->id_str);
> +            if (has_force && force) {
> +                pstrcpy(sn->name, sizeof(sn->name), old_sn->name);
> +                pstrcpy(sn->id_str, sizeof(sn->id_str), old_sn->id_str);
> +
> +                /* Delete old snapshots of the same name */
> +                if (del_existing_snapshots(name, &local_err) < 0) {
> +                    error_propagate(errp, local_err);
> +                    goto the_end;
> +                }
> +            } else {
> +                error_setg(errp, "snapshot '%s' exists, for override use "
> +                           "'force' parameter", name);
> +                goto the_end;
> +            }
>          } else {
>              pstrcpy(sn->name, sizeof(sn->name), name);
>          }
       } else {
           /* cast below needed for OpenBSD where tv_sec is still 'long' */
           localtime_r((const time_t *)&tv.tv_sec, &tm);
> @@ -2308,24 +2321,17 @@ void do_savevm(Monitor *mon, const QDict *qdict)
>          strftime(sn->name, sizeof(sn->name), "vm-%Y%m%d%H%M%S", &tm);

Interestingly, we do not check whether this auto-generated name already
exists.  Not your fault, but could use fixing.

>      }
>  
> -    /* Delete old snapshots of the same name */
> -    if (name && del_existing_snapshots(name, &local_err) < 0) {
> -        monitor_printf(mon, "%s\n", error_get_pretty(local_err));
> -        error_free(local_err);
> -        goto the_end;
> -    }
> -

Your code motion adds two conditions for calling
del_existing_snapshots():

1. has_force && force: feature.  I guess I'd add the feature in a
separate patch, to keep this one as simple as possible.  Your choice.

2. bdrv_snapshot_find() succeeds.  Care to explain why this one's
correct?

>      /* save the VM state */
>      f = qemu_fopen_bdrv(bs, 1);
>      if (!f) {
> -        monitor_printf(mon, "Could not open VM state file\n");
> +        error_setg(errp, "failed to open '%s' file", bdrv_get_device_name(bs));
>          goto the_end;
>      }
> -    ret = qemu_savevm_state(f, NULL);
> +    ret = qemu_savevm_state(f, &local_err);
>      vm_state_size = qemu_ftell(f);
>      qemu_fclose(f);
>      if (ret < 0) {
> -        monitor_printf(mon, "Error %d while writing VM\n", ret);
> +        error_propagate(errp, local_err);
>          goto the_end;
>      }
>  
> @@ -2336,17 +2342,27 @@ void do_savevm(Monitor *mon, const QDict *qdict)
>          if (bdrv_can_snapshot(bs1)) {
>              /* Write VM state size only to the image that contains the state */
>              sn->vm_state_size = (bs == bs1 ? vm_state_size : 0);
> -            ret = bdrv_snapshot_create(bs1, sn, NULL);
> +            ret = bdrv_snapshot_create(bs1, sn, &local_err);
>              if (ret < 0) {
> -                monitor_printf(mon, "Error while creating snapshot on '%s'\n",
> -                               bdrv_get_device_name(bs1));
> +                error_propagate(errp, local_err);

When we go through this failure...

>              }
>          }
>      }
>  
> +    info = g_malloc0(sizeof(SnapshotInfo));
> +    info->id = g_strdup(sn->id_str);
> +    info->name = g_strdup(sn->name);
> +    info->date_nsec = sn->date_nsec;
> +    info->date_sec = sn->date_sec;
> +    info->vm_state_size = vm_state_size;
> +    info->vm_clock_nsec = sn->vm_clock_nsec % 1000000000;
> +    info->vm_clock_sec = sn->vm_clock_nsec / 1000000000;
> +
>   the_end:
>      if (saved_vm_running)
>          vm_start();
> +
> +    return info;

... we return both info and an Error.  Stupid question: is that okay?

>  }
>  
>  void qmp_xen_save_devices_state(const char *filename, Error **errp)

  parent reply	other threads:[~2013-04-09 16:04 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-03-29 14:12 [Qemu-devel] [PATCH v4 00/11] convert savevm to use qapi and introduce qmp command Pavel Hrdina
2013-03-29 14:12 ` [Qemu-devel] [PATCH v4 01/11] block: add error parameter to bdrv_snapshot_create() and related functions Pavel Hrdina
2013-04-09 13:13   ` Markus Armbruster
2013-04-09 13:43     ` Kevin Wolf
2013-04-09 16:21   ` Markus Armbruster
2013-03-29 14:12 ` [Qemu-devel] [PATCH v4 02/11] block: add error parameter to del_existing_snapshots() Pavel Hrdina
2013-04-09 13:27   ` Markus Armbruster
2013-04-09 14:14     ` Luiz Capitulino
2013-04-10  9:57     ` Pavel Hrdina
2013-04-10 11:33       ` Markus Armbruster
2013-04-10 12:06       ` Eric Blake
2013-03-29 14:12 ` [Qemu-devel] [PATCH v4 03/11] savevm: add error parameter to qemu_savevm_state_begin() Pavel Hrdina
2013-04-09 13:34   ` Markus Armbruster
2013-04-09 13:37     ` Markus Armbruster
2013-04-09 13:47       ` Pavel Hrdina
2013-04-09 13:49       ` Markus Armbruster
2013-03-29 14:12 ` [Qemu-devel] [PATCH v4 04/11] savevm: add error parameter to qemu_savevm_state_iterate() Pavel Hrdina
2013-04-09 13:41   ` Markus Armbruster
2013-03-29 14:12 ` [Qemu-devel] [PATCH v4 05/11] savevm: add error parameter to qemu_savevm_state_complete() Pavel Hrdina
2013-04-09 13:56   ` Markus Armbruster
2013-03-29 14:12 ` [Qemu-devel] [PATCH v4 06/11] savevm: add error parameter to qemu_savevm_state() Pavel Hrdina
2013-04-09 14:00   ` Markus Armbruster
2013-03-29 14:12 ` [Qemu-devel] [PATCH v4 07/11] qapi: Convert savevm Pavel Hrdina
2013-03-29 16:12   ` Eric Blake
2013-03-29 16:21     ` Pavel Hrdina
2013-04-09 16:04   ` Markus Armbruster [this message]
2013-04-09 16:12     ` Eric Blake
2013-04-09 17:23       ` Markus Armbruster
2013-04-09 17:46         ` Eric Blake
2013-04-10  8:01           ` Markus Armbruster
2013-03-29 14:12 ` [Qemu-devel] [PATCH v4 08/11] qemu-img: introduce qemu_img_handle_error Pavel Hrdina
2013-04-09 16:10   ` Markus Armbruster
2013-03-29 14:12 ` [Qemu-devel] [PATCH v4 09/11] block: update return value from bdrv_snapshot_create Pavel Hrdina
2013-04-09 16:29   ` Markus Armbruster
2013-03-29 14:12 ` [Qemu-devel] [PATCH v4 10/11] savevm: update return value from qemu_savevm_state Pavel Hrdina
2013-04-09 16:32   ` Markus Armbruster
2013-03-29 14:12 ` [Qemu-devel] [PATCH v4 11/11] savevm: add force parameter to HMP command and return snapshot info Pavel Hrdina
2013-04-09 16:45   ` Markus Armbruster
2013-04-10  8:18 ` [Qemu-devel] [PATCH v4 00/11] convert savevm to use qapi and introduce qmp command Markus Armbruster
2013-04-10 10:53   ` Pavel Hrdina
2013-04-10 12:24     ` Eric Blake
2013-04-10 12:40       ` Luiz Capitulino
2013-04-10 12:49         ` Eric Blake
2013-04-10 13:22           ` Pavel Hrdina
2013-04-10 13:32             ` Luiz Capitulino
2013-04-10 13:50               ` Pavel Hrdina
2013-04-10 14:05       ` Pavel Hrdina
2013-04-10 17:15         ` Eric Blake
2013-04-10 17:33           ` Pavel Hrdina
2013-04-17  2:48             ` Wenchao Xia
2013-04-11  9:20           ` Markus Armbruster
2013-04-15 12:10             ` Kevin Wolf
2013-04-15 13:16               ` Eric Blake

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87d2u3667x.fsf@blackfin.pond.sub.org \
    --to=armbru@redhat.com \
    --cc=lcapitulino@redhat.com \
    --cc=phrdina@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.