qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] QCOW2 multiple disk (not VM) snapshots


From: Kevin Wolf
Subject: Re: [Qemu-devel] QCOW2 multiple disk (not VM) snapshots
Date: Mon, 24 Nov 2008 15:16:27 +0100
User-agent: Thunderbird 2.0.0.17 (X11/20080922)

Hi Mike,

Mike Sun schrieb:
> For a research project, we've been doing a bit of hacking with Xen and
> utilize QCOW disk images as our VBDs. One intriguing thing about the
> QCOW2 format was support for multiple disk snapshots. Unfortunately,
> it seems from what I've been able to glean that support for multiple
> snapshots within a QCOW2 image is really only supported by QEMU's VM
> snapshot feature. Since I'm using Xen and only use QCOW2 disk images,
> I was wondering if there was any way from a tool such as 'qemu-img' to
> take snapshots of the QCOW2 disk image only and not through the
> general QEMU VM snapshot?

You can try the attached patch to qemu-img. I had it already for list,
delete and apply (as that's what I've needed so far), and I just added
create to it to make it complete. However, I didn't test it more than
making sure that it compiles and a new snapshot is listed afterwards.

If you're interested in having real snapshots with Xen, i.e. basically a
combination of xm save/restore and qemu-img snapshot, I also have some
patches to do that. They have quite a few dependencies, though, so they
are not yet upstream.

Kevin
Index: qemu-svn/qemu-img.c
===================================================================
--- qemu-svn.orig/qemu-img.c
+++ qemu-svn/qemu-img.c
@@ -57,6 +57,7 @@ static void help(void)
            "  commit [-f fmt] filename\n"
            "  convert [-c] [-e] [-6] [-f fmt] [-O output_fmt] [-B 
output_base_image] filename [filename2 [...]] output_filename\n"
            "  info [-f fmt] filename\n"
+           "  snapshot [-l|-a snapshot|-c snapshot|-d snapshot] filename\n"
            "\n"
            "Command parameters:\n"
            "  'filename' is a disk image filename\n"
@@ -729,6 +730,121 @@ static int img_info(int argc, char **arg
     return 0;
 }
 
+#define SNAPSHOT_LIST   1
+#define SNAPSHOT_CREATE 2
+#define SNAPSHOT_APPLY  3
+#define SNAPSHOT_DELETE 4
+
+static void img_snapshot(int argc, char **argv)
+{
+    BlockDriverState *bs;
+    QEMUSnapshotInfo sn;
+    char *filename, *snapshot_name = NULL;
+    char c;
+    int ret;
+    int action = 0;
+#ifdef _WIN32
+    struct _timeb tb;
+#else
+    struct timeval tv;
+#endif
+
+    /* Parse commandline parameters */
+    for(;;) {
+        c = getopt(argc, argv, "la:c:d:h");
+        if (c == -1)
+            break;
+        switch(c) {
+        case 'h':
+            help();
+            return;
+        case 'l':
+            if (action) {
+                help();
+                return;
+            }
+            action = SNAPSHOT_LIST;
+            break;
+        case 'a':
+            if (action) {
+                help();
+                return;
+            }
+            action = SNAPSHOT_APPLY;
+            snapshot_name = optarg;
+            break;
+        case 'c':
+            if (action) {
+                help();
+                return;
+            }
+            action = SNAPSHOT_CREATE;
+            snapshot_name = optarg;
+            break;
+        case 'd':
+            if (action) {
+                help();
+                return;
+            }
+            action = SNAPSHOT_DELETE;
+            snapshot_name = optarg;
+            break;
+        }
+    }
+
+    if (optind >= argc)
+        help();
+    filename = argv[optind++];
+
+    /* Open the image */
+    bs = bdrv_new("");
+    if (!bs)
+        error("Not enough memory");
+
+    if (bdrv_open2(bs, filename, 0, NULL) < 0) {
+        error("Could not open '%s'", filename);
+    }
+
+    /* Perform the requested action */
+    switch(action) {
+    case SNAPSHOT_LIST:
+        dump_snapshots(bs);
+        break;
+
+    case SNAPSHOT_CREATE:
+        memset(&sn, 0, sizeof(sn));
+        pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
+#ifdef _WIN32
+        _ftime(&tb);
+        sn.date_sec = tb.time;
+        sn.date_nsec = tb.millitm * 1000000;
+#else
+        gettimeofday(&tv, NULL);
+        sn.date_sec = tv.tv_sec;
+        sn.date_nsec = tv.tv_usec * 1000;
+#endif
+        ret = bdrv_snapshot_create(bs, &sn);
+        break;
+
+    case SNAPSHOT_APPLY:
+        ret = bdrv_snapshot_goto(bs, snapshot_name);
+        if (ret)
+            error("Could not apply snapshot '%s': %d (%s)",
+                snapshot_name, strerror(ret), ret);
+        break;
+
+    case SNAPSHOT_DELETE:
+        ret = bdrv_snapshot_delete(bs, snapshot_name);
+        if (ret)
+            error("Could not delete snapshot '%s': %d (%s)",
+                snapshot_name, strerror(ret), ret);
+        break;
+    }
+
+    /* Cleanup */
+    bdrv_delete(bs);
+}
+
 int main(int argc, char **argv)
 {
     const char *cmd;
@@ -746,6 +862,8 @@ int main(int argc, char **argv)
         img_convert(argc, argv);
     } else if (!strcmp(cmd, "info")) {
         img_info(argc, argv);
+    } else if (!strcmp(cmd, "snapshot")) {
+        img_snapshot(argc, argv);
     } else {
         help();
     }

reply via email to

[Prev in Thread] Current Thread [Next in Thread]