qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org
Cc: kwolf@redhat.com, aliguori@us.ibm.com, stefanha@gmail.com,
	blauwirbel@gmail.com, pbonzini@redhat.com,
	Wenchao Xia <xiawenc@linux.vnet.ibm.com>
Subject: [Qemu-devel] [PATCH 6/6] snapshot: human monitor interface
Date: Mon, 17 Dec 2012 14:25:09 +0800	[thread overview]
Message-ID: <1355725509-5429-7-git-send-email-xiawenc@linux.vnet.ibm.com> (raw)
In-Reply-To: <1355725509-5429-1-git-send-email-xiawenc@linux.vnet.ibm.com>

  This patch add support in human monitor to create/delete/check
internal snapshot on a single blk device.
  To make info command get parameter, added a new info handler
type which can take QDict as parameter.

Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
---
 hmp-commands.hx |   50 +++++++++++++++++++++++++++++++++++++-------------
 hmp.c           |   30 +++++++++++++++++++++++++-----
 hmp.h           |    1 +
 monitor.c       |   21 +++++++++++++++------
 savevm.c        |   55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 sysemu.h        |    2 +-
 6 files changed, 133 insertions(+), 26 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 010b8c9..ee74723 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -983,17 +983,22 @@ ETEXI
 
     {
         .name       = "snapshot_blkdev",
-        .args_type  = "reuse:-n,device:B,snapshot-file:s?,format:s?",
-        .params     = "[-n] device [new-image-file] [format]",
-        .help       = "initiates a live snapshot\n\t\t\t"
-                      "of device. If a new image file is specified, the\n\t\t\t"
-                      "new image file will become the new root image.\n\t\t\t"
-                      "If format is specified, the snapshot file will\n\t\t\t"
-                      "be created in that format. Otherwise the\n\t\t\t"
-                      "snapshot will be internal! (currently unsupported).\n\t\t\t"
-                      "The default format is qcow2.  The -n flag requests QEMU\n\t\t\t"
-                      "to reuse the image found in new-image-file, instead of\n\t\t\t"
-                      "recreating it from scratch.",
+        .args_type  = "internal:-i,reuse:-n,device:B,snapshot-file:s?,format:s?",
+        .params     = "[-i] [-n] device [new-image-file] [format]",
+        .help       = "initiates a live snapshot of device.\n\t\t\t"
+                      "  The -i flag requests QEMU to create internal snapshot\n\t\t\t"
+                      "instead of external one.\n\t\t\t"
+                      "  The -n flag requests QEMU to use existing snapshot\n\t\t\t"
+                      "instead of creating new snapshot, which would fails if\n\t\t\t"
+                      "snapshot does not exist ahead.\n\t\t\t"
+                      "  new-image-file is the snapshot's name, in external case\n\t\t\t"
+                      "it is the new image's name which will become the new root\n\t\t\t"
+                      "image and must be specified, in internal case it is the\n\t\t\t"
+                      "record's name and if not specified QEMU will create\n\t\t\t"
+                      "internal snapshot with name generated according to time.\n\t\t\t"
+                      "  format is only valid in external case, which is the new\n\t\t\t"
+                      "snapshot image's format. If not sepcified default format\n\t\t\t"
+                      "qcow2 will be used.",
         .mhandler.cmd = hmp_snapshot_blkdev,
     },
 
@@ -1004,6 +1009,25 @@ Snapshot device, using snapshot file as target if provided
 ETEXI
 
     {
+        .name       = "snapshot_delete_blkdev",
+        .args_type  = "internal:-i,device:B,snapshot-file:s",
+        .params     = "[-i] device new-image-file",
+        .help       = "delete a snapshot  synchronous.\n\t\t\t"
+                      "  The -i flag requests QEMU to delete internal snapshot\n\t\t\t"
+                      "instead of external one.\n\t\t\t"
+                      "  new-image-file is the snapshot's name, in external case\n\t\t\t"
+                      "it is the image's name which is not supported now.\n\t\t\t"
+                      "in internal case it is the snapshot record's id or name.",
+        .mhandler.cmd = hmp_snapshot_delete_blkdev,
+    },
+
+STEXI
+@item snapshot_delete_blkdev
+@findex snapshot_delete_blkdev
+Delete a snapshot on a block device.
+ETEXI
+
+    {
         .name       = "drive_mirror",
         .args_type  = "reuse:-n,full:-f,device:B,target:s,format:s?",
         .params     = "[-n] [-f] device target [format]",
@@ -1486,8 +1510,8 @@ ETEXI
 
     {
         .name       = "info",
-        .args_type  = "item:s?",
-        .params     = "[subcommand]",
+        .args_type  = "item:s?,params:s?",
+        .params     = "[subcommand] [params]",
         .help       = "show various information about the system state",
         .mhandler.cmd = do_info,
     },
diff --git a/hmp.c b/hmp.c
index 180ba2b..f247f51 100644
--- a/hmp.c
+++ b/hmp.c
@@ -806,20 +806,40 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict)
     const char *filename = qdict_get_try_str(qdict, "snapshot-file");
     const char *format = qdict_get_try_str(qdict, "format");
     int reuse = qdict_get_try_bool(qdict, "reuse", 0);
+    int internal = qdict_get_try_bool(qdict, "internal", 0);
     enum NewImageMode mode;
+    enum SnapshotType type;
     Error *errp = NULL;
 
-    if (!filename) {
-        /* In the future, if 'snapshot-file' is not specified, the snapshot
-           will be taken internally. Today it's actually required. */
+    if ((!internal) && (!filename)) {
+        /* in external case filename must be set, should we generate
+         it automatically? */
         error_set(&errp, QERR_MISSING_PARAMETER, "snapshot-file");
         hmp_handle_error(mon, &errp);
         return;
     }
-
+    type = internal ? SNAPSHOT_TYPE_INTERNAL : SNAPSHOT_TYPE_EXTERNAL;
     mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS;
     qmp_blockdev_snapshot_sync(device, filename, !!format, format,
-                               true, mode, &errp);
+                               true, mode, true, type, &errp);
+    hmp_handle_error(mon, &errp);
+}
+
+void hmp_snapshot_delete_blkdev(Monitor *mon, const QDict *qdict)
+{
+    const char *device = qdict_get_str(qdict, "device");
+    const char *filename = qdict_get_try_str(qdict, "snapshot-file");
+    int internal = qdict_get_try_bool(qdict, "internal", 0);
+    enum SnapshotType type;
+    Error *errp = NULL;
+
+    if (!internal) {
+        error_setg(&errp, "external snapshot delete not supported now.");
+        hmp_handle_error(mon, &errp);
+        return;
+    }
+    type = internal ? SNAPSHOT_TYPE_INTERNAL : SNAPSHOT_TYPE_EXTERNAL;
+    qmp_blockdev_snapshot_delete_sync(device, filename, true, type, &errp);
     hmp_handle_error(mon, &errp);
 }
 
diff --git a/hmp.h b/hmp.h
index 0ab03be..2ea67be 100644
--- a/hmp.h
+++ b/hmp.h
@@ -51,6 +51,7 @@ void hmp_block_passwd(Monitor *mon, const QDict *qdict);
 void hmp_balloon(Monitor *mon, const QDict *qdict);
 void hmp_block_resize(Monitor *mon, const QDict *qdict);
 void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict);
+void hmp_snapshot_delete_blkdev(Monitor *mon, const QDict *qdict);
 void hmp_drive_mirror(Monitor *mon, const QDict *qdict);
 void hmp_migrate_cancel(Monitor *mon, const QDict *qdict);
 void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict);
diff --git a/monitor.c b/monitor.c
index c0e32d6..81de470 100644
--- a/monitor.c
+++ b/monitor.c
@@ -124,11 +124,14 @@ typedef struct mon_cmd_t {
     void (*user_print)(Monitor *mon, const QObject *data);
     union {
         void (*info)(Monitor *mon);
+        void (*info_qdict)(Monitor *mon, const QDict *qdict);
         void (*cmd)(Monitor *mon, const QDict *qdict);
-        int  (*cmd_new)(Monitor *mon, const QDict *params, QObject **ret_data);
+        int  (*cmd_new)(Monitor *mon, const QDict *params,
+                        QObject **ret_data);
         int  (*cmd_async)(Monitor *mon, const QDict *params,
                           MonitorCompletion *cb, void *opaque);
     } mhandler;
+    int info_cmd_need_qdict;
     int flags;
 } mon_cmd_t;
 
@@ -824,7 +827,11 @@ static void do_info(Monitor *mon, const QDict *qdict)
         goto help;
     }
 
-    cmd->mhandler.info(mon);
+    if (cmd->info_cmd_need_qdict) {
+        cmd->mhandler.info_qdict(mon, qdict);
+    } else {
+        cmd->mhandler.info(mon);
+    }
     return;
 
 help:
@@ -2605,10 +2612,12 @@ static mon_cmd_t info_cmds[] = {
     },
     {
         .name       = "snapshots",
-        .args_type  = "",
-        .params     = "",
-        .help       = "show the currently saved VM snapshots",
-        .mhandler.info = do_info_snapshots,
+        .args_type  = "device:B?",
+        .params     = "[device]",
+        .help       = "show the currently saved VM snapshots or snapshots on "
+                      "a single device.",
+        .mhandler.info_qdict = do_info_snapshots,
+        .info_cmd_need_qdict = 1,
     },
     {
         .name       = "status",
diff --git a/savevm.c b/savevm.c
index c027529..5982aa9 100644
--- a/savevm.c
+++ b/savevm.c
@@ -2336,7 +2336,7 @@ void do_delvm(Monitor *mon, const QDict *qdict)
     }
 }
 
-void do_info_snapshots(Monitor *mon)
+static void do_info_snapshots_vm(Monitor *mon)
 {
     BlockDriverState *bs, *bs1;
     QEMUSnapshotInfo *sn_tab, *sn, s, *sn_info = &s;
@@ -2400,6 +2400,59 @@ void do_info_snapshots(Monitor *mon)
 
 }
 
+static void do_info_snapshots_blk(Monitor *mon, const char *device)
+{
+    BlockDriverState *bs;
+    QEMUSnapshotInfo *sn_tab, *sn;
+    int nb_sns, i;
+    char buf[256];
+
+    /* find the target bs */
+    bs = bdrv_find(device);
+    if (!bs) {
+        monitor_printf(mon, "Device '%s' not found.\n", device);
+        return ;
+    }
+
+    if (!bdrv_can_snapshot(bs)) {
+        monitor_printf(mon, "Device '%s' can't have snapshot.\n", device);
+        return ;
+    }
+
+    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
+    if (nb_sns < 0) {
+        monitor_printf(mon, "Device %s bdrv_snapshot_list: error %d\n",
+                       device, nb_sns);
+        return;
+    }
+
+    if (nb_sns == 0) {
+        monitor_printf(mon, "There is no snapshot available.\n");
+        return;
+    }
+
+    monitor_printf(mon, "Device %s:\n", device);
+    monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
+    for (i = 0; i < nb_sns; i++) {
+        sn = &sn_tab[i];
+        monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
+    }
+    g_free(sn_tab);
+    return;
+}
+
+void do_info_snapshots(Monitor *mon, const QDict *qdict)
+{
+    /* Todo, there should be a layer rebuild qdict before enter this func. */
+    const char *device = qdict_get_try_str(qdict, "params");
+    if (!device) {
+        do_info_snapshots_vm(mon);
+    } else {
+        do_info_snapshots_blk(mon, device);
+    }
+    return;
+}
+
 void vmstate_register_ram(MemoryRegion *mr, DeviceState *dev)
 {
     qemu_ram_set_idstr(memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK,
diff --git a/sysemu.h b/sysemu.h
index 1b6add2..a1254bf 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -68,7 +68,7 @@ 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);
+void do_info_snapshots(Monitor *mon, const QDict *qdict);
 
 void qemu_announce_self(void);
 
-- 
1.7.1

  parent reply	other threads:[~2012-12-17  6:35 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-12-17  6:25 [Qemu-devel] [PATCH 0/6] snapshot: take snapshots in unified way Wenchao Xia
2012-12-17  6:25 ` [Qemu-devel] [PATCH 1/6] snapshot: export function in block.c Wenchao Xia
2012-12-21 18:13   ` Juan Quintela
2012-12-25  4:31     ` Wenchao Xia
2013-01-04 14:49   ` Stefan Hajnoczi
2013-01-05  8:26     ` Wenchao Xia
2013-01-07 16:43   ` Kevin Wolf
2013-01-08  2:25     ` Wenchao Xia
2013-01-08 10:37       ` Kevin Wolf
2013-01-09  4:32         ` Wenchao Xia
2012-12-17  6:25 ` [Qemu-devel] [PATCH 2/6] snapshot: add error set function Wenchao Xia
2012-12-20 21:36   ` Eric Blake
2012-12-21  2:37     ` Wenchao Xia
2013-01-04 14:55   ` Stefan Hajnoczi
2013-01-05  8:27     ` Wenchao Xia
2012-12-17  6:25 ` [Qemu-devel] [PATCH 3/6] snapshot: design of common API to take snapshots Wenchao Xia
2012-12-21 18:48   ` Eric Blake
2012-12-25  5:25     ` Wenchao Xia
2012-12-21 18:49   ` Juan Quintela
2012-12-25  5:24     ` Wenchao Xia
2012-12-17  6:25 ` [Qemu-devel] [PATCH 4/6] snapshot: implemention " Wenchao Xia
2012-12-17  6:36   ` Dietmar Maurer
2012-12-17  7:38     ` Wenchao Xia
2012-12-17  7:52       ` Dietmar Maurer
2012-12-17  8:52         ` Wenchao Xia
2012-12-17  9:58           ` Dietmar Maurer
2012-12-20 22:19             ` Eric Blake
2012-12-21  3:01               ` Wenchao Xia
2012-12-21  6:20                 ` Dietmar Maurer
2013-01-04 16:13                   ` Stefan Hajnoczi
2012-12-17 10:32           ` Dietmar Maurer
2012-12-18 10:29             ` Wenchao Xia
2012-12-18 10:36               ` Dietmar Maurer
2012-12-19  3:34                 ` Wenchao Xia
2012-12-19  4:55                   ` Dietmar Maurer
2012-12-19  5:37                     ` Wenchao Xia
2012-12-21 18:48   ` Juan Quintela
2012-12-25  5:16     ` Wenchao Xia
2012-12-17  6:25 ` [Qemu-devel] [PATCH 5/6] snapshot: qmp interface Wenchao Xia
2013-01-02 14:52   ` Eric Blake
2013-01-04  6:02     ` Wenchao Xia
2013-01-04 13:57       ` Eric Blake
2013-01-04 16:22   ` Stefan Hajnoczi
2013-01-05  8:38     ` Wenchao Xia
2012-12-17  6:25 ` Wenchao Xia [this message]
2013-01-04 15:44   ` [Qemu-devel] [PATCH 6/6] snapshot: human monitor interface Stefan Hajnoczi
2013-01-05  8:36     ` Wenchao Xia

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=1355725509-5429-7-git-send-email-xiawenc@linux.vnet.ibm.com \
    --to=xiawenc@linux.vnet.ibm.com \
    --cc=aliguori@us.ibm.com \
    --cc=blauwirbel@gmail.com \
    --cc=kwolf@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@gmail.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).