File snapshot-ioemu-save.patch of Package xen.import4929

Index: xen-4.0.2-testing/tools/ioemu-qemu-xen/savevm.c
===================================================================
--- xen-4.0.2-testing.orig/tools/ioemu-qemu-xen/savevm.c
+++ xen-4.0.2-testing/tools/ioemu-qemu-xen/savevm.c
@@ -28,6 +28,7 @@
 #include "sysemu.h"
 #include "qemu-timer.h"
 #include "qemu-char.h"
+#include "block_int.h"
 #include "block.h"
 #include "audio/audio.h"
 #include "migration.h"
@@ -1015,6 +1016,86 @@ static int bdrv_snapshot_find(BlockDrive
     return ret;
 }
 
+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;
+}
+
 #ifndef CONFIG_DM
 
 void do_savevm(const char *name)
Index: xen-4.0.2-testing/tools/ioemu-qemu-xen/i386-dm/helper2.c
===================================================================
--- xen-4.0.2-testing.orig/tools/ioemu-qemu-xen/i386-dm/helper2.c
+++ xen-4.0.2-testing/tools/ioemu-qemu-xen/i386-dm/helper2.c
@@ -112,6 +112,9 @@ int send_vcpu = 0;
 //the evtchn port for polling the notification,
 evtchn_port_t *ioreq_local_port;
 
+/** Name of the snapshot which should be saved */
+char* snapshot_name;
+
 CPUX86State *cpu_x86_init(const char *cpu_model)
 {
     CPUX86State *env;
@@ -556,6 +559,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();
 
@@ -583,11 +587,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-4.0.2-testing/tools/ioemu-qemu-xen/qemu-xen.h
===================================================================
--- xen-4.0.2-testing.orig/tools/ioemu-qemu-xen/qemu-xen.h
+++ xen-4.0.2-testing/tools/ioemu-qemu-xen/qemu-xen.h
@@ -34,6 +34,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);
@@ -68,6 +77,7 @@ int xenstore_fd(void);
 void xenstore_process_event(void *opaque);
 void xenstore_record_dm(const char *subpath, const char *state);
 void xenstore_record_dm_state(const char *state);
+void xenstore_record_dm_error(const 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-4.0.2-testing/tools/ioemu-qemu-xen/xenstore.c
===================================================================
--- xen-4.0.2-testing.orig/tools/ioemu-qemu-xen/xenstore.c
+++ xen-4.0.2-testing/tools/ioemu-qemu-xen/xenstore.c
@@ -17,6 +17,7 @@
 
 #include "exec-all.h"
 #include "sysemu.h"
+#include "qemu-xen.h"
 
 #include "console.h"
 #include "hw.h"
@@ -868,6 +869,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) {
@@ -883,7 +885,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;
@@ -1016,6 +1029,13 @@ void xenstore_record_dm_state(const char
     xenstore_record_dm("state", state);
 }
 
+void xenstore_record_dm_error(const char *errmsg)
+{
+    fprintf(logfile, "%s\n", errmsg);
+    xenstore_record_dm("error", errmsg);
+    xenstore_record_dm_state("error");
+}
+
 static void xenstore_process_media_change_event(char **vec)
 {
     char *media_present = NULL;
openSUSE Build Service is sponsored by