File snapshot-ioemu-save.patch of Package xen

Index: xen-3.3.1-testing/tools/ioemu-remote/block.h
===================================================================
--- xen-3.3.1-testing.orig/tools/ioemu-remote/block.h
+++ xen-3.3.1-testing/tools/ioemu-remote/block.h
@@ -103,6 +103,7 @@ int qemu_key_check(BlockDriverState *bs,
 
 /* Ensure contents are flushed to disk.  */
 int bdrv_flush(BlockDriverState *bs);
+int bdrv_flush_all(void);
 
 #define BDRV_TYPE_HD     0
 #define BDRV_TYPE_CDROM  1
Index: xen-3.3.1-testing/tools/ioemu-remote/block.c
===================================================================
--- xen-3.3.1-testing.orig/tools/ioemu-remote/block.c
+++ xen-3.3.1-testing/tools/ioemu-remote/block.c
@@ -950,6 +950,21 @@ int bdrv_flush(BlockDriverState *bs)
     return ret;
 }
 
+int bdrv_flush_all(void)
+{
+    BlockDriverState *bs;
+    int ret = 0, ret1;
+
+    for (bs = bdrv_first; bs != NULL; bs = bs->next)
+        if (bs->drv && !bdrv_is_read_only(bs) &&
+            (!bdrv_is_removable(bs) || bdrv_is_inserted(bs))) {
+            ret1 = bdrv_flush(bs);
+            if (ret1) ret = ret1;
+        }
+
+    return ret;
+}
+
 #ifndef QEMU_IMG
 void bdrv_info(void)
 {
Index: xen-3.3.1-testing/tools/ioemu-remote/xen-vl-extra.c
===================================================================
--- xen-3.3.1-testing.orig/tools/ioemu-remote/xen-vl-extra.c
+++ xen-3.3.1-testing/tools/ioemu-remote/xen-vl-extra.c
@@ -8,12 +8,18 @@
  * there is only one place where this file is included. */
 
 #include "qemu-xen.h"
+#include "block_int.h"
 
 /* forward declarations of things in vl.c */
 
 static int qemu_savevm_state(QEMUFile *f);
 static int qemu_loadvm_state(QEMUFile *f);
 
+static int bdrv_can_snapshot(BlockDriverState *bs);
+static int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
+    const char *name);
+
+
 /* We use simpler state save/load functions for Xen */
 
 void do_savevm(const char *name)
@@ -85,6 +91,86 @@ void do_loadvm(const char *name)
         vm_start();
 }
 
+int save_disk_snapshots(const char* name)
+{
+    BlockDriverState *bs;
+    QEMUSnapshotInfo sn, old_sn;
+    struct timeval tv;
+    int saved_vm_running;
+    int can_snapshot;
+    int i;
+    int ret = 0;
+
+    /* Deal with all aio submit */
+    qemu_aio_flush();
+    /* Do fsync at backend fs */
+    ret = bdrv_flush_all();
+    if (ret)
+        fprintf(stderr, "Fsync error[%d] when do snapshot[%s]\n", ret, name);
+
+    saved_vm_running = vm_running;
+    vm_stop(0);
+
+    /* Ensure that all images support snapshots or are read-only */
+    for(i = 0; i < MAX_DRIVES; i++) {
+        bs = drives_table[i].bdrv;
+
+        if (!bs || !bs->drv)
+            continue;
+
+        can_snapshot = bs->drv->bdrv_snapshot_create && bdrv_can_snapshot(bs);
+        if (!bdrv_is_read_only(bs) && !can_snapshot) {
+            fprintf(stderr, "Error: bdrv %s (%s) doesn't support snapshots\n",
+                bdrv_get_device_name(bs), bs->drv->format_name);
+            ret = -ENOTSUP;
+            goto the_end;
+        }
+    }
+
+    /* fill auxiliary fields */
+    memset(&sn, 0, sizeof(sn));
+    gettimeofday(&tv, NULL);
+    sn.date_sec = tv.tv_sec;
+    sn.date_nsec = tv.tv_usec * 1000;
+    sn.vm_clock_nsec = qemu_get_clock(vm_clock);
+    pstrcpy(sn.name, sizeof(sn.name), name);
+
+    for(i = 0; i < MAX_DRIVES; i++) {
+        bs = drives_table[i].bdrv;
+
+        /* No snapshots on read-only images */
+        if (!bs || !bs->drv || bdrv_is_read_only(bs))
+            continue;
+
+        /* Delete old snapshot of the same name */
+        if (bdrv_snapshot_find(bs, &old_sn, name) >= 0) {
+            ret = bdrv_snapshot_delete(bs, old_sn.id_str);
+            if (ret < 0) {
+                fprintf(stderr, "Error while deleting snapshot on '%s'\n",
+                            bdrv_get_device_name(bs));
+            }
+        }
+
+        /* Create the snapshot */
+        fprintf(stderr, "Creating snapshot on '%s' (%s)\n",
+            bdrv_get_device_name(bs), bs->drv->format_name);
+        ret = bdrv_snapshot_create(bs, &sn);
+        if (ret < 0) {
+            fprintf(stderr, "Error while creating snapshot on '%s': %d (%s)\n",
+                        bdrv_get_device_name(bs), ret, strerror(-ret));
+            goto the_end;
+        }
+    }
+
+    fprintf(stderr, "Created all snapshots\n");
+
+the_end:
+    if (saved_vm_running)
+        vm_start();
+
+    return ret;
+}
+
 struct qemu_alarm_timer;
 static int unix_start_timer(struct qemu_alarm_timer *t) { return 0; }
 static void unix_stop_timer(struct qemu_alarm_timer *t) { }
Index: xen-3.3.1-testing/tools/ioemu-remote/i386-dm/helper2.c
===================================================================
--- xen-3.3.1-testing.orig/tools/ioemu-remote/i386-dm/helper2.c
+++ xen-3.3.1-testing/tools/ioemu-remote/i386-dm/helper2.c
@@ -101,6 +101,9 @@ int send_vcpu = 0;
 #define NR_CPUS 32
 evtchn_port_t ioreq_local_port[NR_CPUS];
 
+/** Name of the snapshot which should be saved */
+char* snapshot_name;
+
 CPUX86State *cpu_x86_init(const char *cpu_model)
 {
     CPUX86State *env;
@@ -547,6 +550,7 @@ int main_loop(void)
     int evtchn_fd = xce_handle == -1 ? -1 : xc_evtchn_fd(xce_handle);
     char *qemu_file;
     fd_set fds;
+    int ret;
 
     main_loop_prepare();
 
@@ -574,11 +578,43 @@ int main_loop(void)
         main_loop_wait(1); /* For the select() on events */
 
         /* Save the device state */
-        asprintf(&qemu_file, "/var/lib/xen/qemu-save.%d", domid);
-        do_savevm(qemu_file);
-        free(qemu_file);
+        switch (xen_pause_requested) {
+        case SUSPEND_SAVEVM:
+            asprintf(&qemu_file, "/var/lib/xen/qemu-save.%d", domid);
+            do_savevm(qemu_file);
+            free(qemu_file);
+            xenstore_record_dm_state("paused");
+            break;
+
+        case SUSPEND_SNAPSHOT:
+            if (snapshot_name != NULL) {
+                ret = save_disk_snapshots(snapshot_name);
+                free(snapshot_name);
+                snapshot_name = NULL;
+
+                switch (ret) {
+                case 0:
+                    xenstore_record_dm_state("paused");
+                    break;
+                case -ENOTSUP:
+                    xenstore_record_dm_error("Snapshots not supported on all"
+                        " attached read-write disks");
+                    break;
+                case -ENOENT:
+                    xenstore_record_dm_error("A snapshot with the same name"
+                        " already exists");
+                    break;
+                default:
+                    xenstore_record_dm_error("An error occurred while saving"
+                        " the snapshot");
+                    break;
+                }
+            } else {
+                xenstore_record_dm_error("No snapshot name given");
+            }
+            break;
+        }
 
-        xenstore_record_dm_state("paused");
 
         /* Wait to be allowed to continue */
         while (xen_pause_requested) {
Index: xen-3.3.1-testing/tools/ioemu-remote/qemu-xen.h
===================================================================
--- xen-3.3.1-testing.orig/tools/ioemu-remote/qemu-xen.h
+++ xen-3.3.1-testing/tools/ioemu-remote/qemu-xen.h
@@ -14,6 +14,15 @@ void     qemu_invalidate_map_cache(void)
 #define mapcache_lock()   ((void)0)
 #define mapcache_unlock() ((void)0)
 
+/* Reason for xen_pause_requested */
+enum {
+    SUSPEND_SAVEVM      = 1,
+    SUSPEND_SNAPSHOT    = 2
+};
+
+/* xen-vl-extra.c */
+int save_disk_snapshots(const char* name);
+
 /* helper2.c */
 extern long time_offset;
 void timeoffset_get(void);
@@ -43,6 +52,7 @@ int xenstore_fd(void);
 void xenstore_process_event(void *opaque);
 void xenstore_record_dm(char *subpath, char *state);
 void xenstore_record_dm_state(char *state);
+void xenstore_record_dm_error(char *errmsg);
 void xenstore_check_new_media_present(int timeout);
 void xenstore_write_vncport(int vnc_display);
 void xenstore_read_vncpasswd(int domid, char *pwbuf, size_t pwbuflen);
Index: xen-3.3.1-testing/tools/ioemu-remote/xenstore.c
===================================================================
--- xen-3.3.1-testing.orig/tools/ioemu-remote/xenstore.c
+++ xen-3.3.1-testing/tools/ioemu-remote/xenstore.c
@@ -24,6 +24,7 @@
 
 #include "exec-all.h"
 #include "sysemu.h"
+#include "qemu-xen.h"
 
 #include "hw.h"
 #include "pci.h"
@@ -604,6 +605,7 @@ static void xenstore_process_dm_command_
 {
     char *path = NULL, *command = NULL, *par = NULL;
     unsigned int len;
+    extern char* snapshot_name;
 
     if (pasprintf(&path, 
                   "/local/domain/0/device-model/%u/command", domid) == -1) {
@@ -616,7 +618,18 @@ static void xenstore_process_dm_command_
     
     if (!strncmp(command, "save", len)) {
         fprintf(logfile, "dm-command: pause and save state\n");
-        xen_pause_requested = 1;
+        xen_pause_requested = SUSPEND_SAVEVM;
+    } else if (!strncmp(command, "snapshot", len)) {
+        fprintf(logfile, "dm-command: pause and snapshot disks\n");
+        xen_pause_requested = SUSPEND_SNAPSHOT;
+
+        if (pasprintf(&path,
+                "/local/domain/0/device-model/%u/parameter", domid) == -1) {
+            fprintf(logfile, "out of memory reading dm command parameter\n");
+            goto out;
+        }
+
+        snapshot_name = xs_read(xsh, XBT_NULL, path, &len);
     } else if (!strncmp(command, "continue", len)) {
         fprintf(logfile, "dm-command: continue after state save\n");
         xen_pause_requested = 0;
@@ -680,6 +693,13 @@ void xenstore_record_dm_state(char *stat
     xenstore_record_dm("state", state);
 }
 
+void xenstore_record_dm_error(char *errmsg)
+{
+    fprintf(logfile, "%s\n", errmsg);
+    xenstore_record_dm("error", errmsg);
+    xenstore_record_dm_state("error");
+}
+
 void xenstore_process_media_change_event(char **vec)
 {
     char *media_present = NULL;
openSUSE Build Service is sponsored by