2010-03-01 16:05:50 +01:00
|
|
|
Index: xen-4.0.0-testing/tools/ioemu-remote/savevm.c
|
|
|
|
===================================================================
|
|
|
|
--- xen-4.0.0-testing.orig/tools/ioemu-remote/savevm.c
|
|
|
|
+++ xen-4.0.0-testing/tools/ioemu-remote/savevm.c
|
2009-05-04 18:38:09 +02:00
|
|
|
@@ -28,6 +28,7 @@
|
|
|
|
#include "sysemu.h"
|
|
|
|
#include "qemu-timer.h"
|
|
|
|
#include "qemu-char.h"
|
2008-07-19 01:04:37 +02:00
|
|
|
+#include "block_int.h"
|
2009-05-04 18:38:09 +02:00
|
|
|
#include "block.h"
|
|
|
|
#include "audio/audio.h"
|
|
|
|
#include "migration.h"
|
|
|
|
@@ -1015,6 +1016,86 @@ static int bdrv_snapshot_find(BlockDrive
|
|
|
|
return ret;
|
2008-07-19 01:04:37 +02:00
|
|
|
}
|
2008-08-18 00:24:29 +02:00
|
|
|
|
2008-07-19 01:04:37 +02:00
|
|
|
+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;
|
|
|
|
+
|
2009-05-04 18:38:09 +02:00
|
|
|
+ /* 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);
|
|
|
|
+
|
2008-07-19 01:04:37 +02:00
|
|
|
+ saved_vm_running = vm_running;
|
|
|
|
+ vm_stop(0);
|
|
|
|
+
|
|
|
|
+ /* Ensure that all images support snapshots or are read-only */
|
2008-08-18 00:24:29 +02:00
|
|
|
+ for(i = 0; i < MAX_DRIVES; i++) {
|
|
|
|
+ bs = drives_table[i].bdrv;
|
2008-07-19 01:04:37 +02:00
|
|
|
+
|
|
|
|
+ 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);
|
|
|
|
+
|
2008-08-18 00:24:29 +02:00
|
|
|
+ for(i = 0; i < MAX_DRIVES; i++) {
|
|
|
|
+ bs = drives_table[i].bdrv;
|
2008-07-19 01:04:37 +02:00
|
|
|
+
|
|
|
|
+ /* 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;
|
|
|
|
+}
|
|
|
|
+
|
2009-05-04 18:38:09 +02:00
|
|
|
#ifndef CONFIG_DM
|
|
|
|
|
|
|
|
void do_savevm(const char *name)
|
2010-03-01 16:05:50 +01:00
|
|
|
Index: xen-4.0.0-testing/tools/ioemu-remote/i386-dm/helper2.c
|
|
|
|
===================================================================
|
|
|
|
--- xen-4.0.0-testing.orig/tools/ioemu-remote/i386-dm/helper2.c
|
|
|
|
+++ xen-4.0.0-testing/tools/ioemu-remote/i386-dm/helper2.c
|
2009-05-04 18:38:09 +02:00
|
|
|
@@ -109,6 +109,9 @@ int send_vcpu = 0;
|
2010-01-16 01:12:54 +01:00
|
|
|
//the evtchn port for polling the notification,
|
|
|
|
evtchn_port_t *ioreq_local_port;
|
2008-07-19 01:04:37 +02:00
|
|
|
|
|
|
|
+/** Name of the snapshot which should be saved */
|
|
|
|
+char* snapshot_name;
|
|
|
|
+
|
2008-08-18 00:24:29 +02:00
|
|
|
CPUX86State *cpu_x86_init(const char *cpu_model)
|
2008-07-19 01:04:37 +02:00
|
|
|
{
|
|
|
|
CPUX86State *env;
|
2010-01-16 01:12:54 +01:00
|
|
|
@@ -553,6 +556,7 @@ int main_loop(void)
|
2008-11-21 15:57:01 +01:00
|
|
|
int evtchn_fd = xce_handle == -1 ? -1 : xc_evtchn_fd(xce_handle);
|
|
|
|
char *qemu_file;
|
|
|
|
fd_set fds;
|
|
|
|
+ int ret;
|
|
|
|
|
|
|
|
main_loop_prepare();
|
|
|
|
|
2010-01-16 01:12:54 +01:00
|
|
|
@@ -580,11 +584,43 @@ int main_loop(void)
|
2008-07-19 01:04:37 +02:00
|
|
|
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);
|
2008-08-18 00:24:29 +02:00
|
|
|
+ switch (xen_pause_requested) {
|
2008-07-19 01:04:37 +02:00
|
|
|
+ case SUSPEND_SAVEVM:
|
|
|
|
+ asprintf(&qemu_file, "/var/lib/xen/qemu-save.%d", domid);
|
|
|
|
+ do_savevm(qemu_file);
|
|
|
|
+ free(qemu_file);
|
2008-11-21 15:57:01 +01:00
|
|
|
+ xenstore_record_dm_state("paused");
|
2008-07-19 01:04:37 +02:00
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SUSPEND_SNAPSHOT:
|
|
|
|
+ if (snapshot_name != NULL) {
|
2008-11-21 15:57:01 +01:00
|
|
|
+ ret = save_disk_snapshots(snapshot_name);
|
2008-07-19 01:04:37 +02:00
|
|
|
+ free(snapshot_name);
|
|
|
|
+ snapshot_name = NULL;
|
2008-11-21 15:57:01 +01:00
|
|
|
+
|
|
|
|
+ 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;
|
|
|
|
+ }
|
2008-07-19 01:04:37 +02:00
|
|
|
+ } else {
|
2008-11-21 15:57:01 +01:00
|
|
|
+ xenstore_record_dm_error("No snapshot name given");
|
2008-07-19 01:04:37 +02:00
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
|
2008-11-21 15:57:01 +01:00
|
|
|
- xenstore_record_dm_state("paused");
|
2008-07-19 01:04:37 +02:00
|
|
|
|
2008-11-21 15:57:01 +01:00
|
|
|
/* Wait to be allowed to continue */
|
|
|
|
while (xen_pause_requested) {
|
2010-03-01 16:05:50 +01:00
|
|
|
Index: xen-4.0.0-testing/tools/ioemu-remote/qemu-xen.h
|
|
|
|
===================================================================
|
|
|
|
--- xen-4.0.0-testing.orig/tools/ioemu-remote/qemu-xen.h
|
|
|
|
+++ xen-4.0.0-testing/tools/ioemu-remote/qemu-xen.h
|
2009-05-04 18:38:09 +02:00
|
|
|
@@ -34,6 +34,15 @@ void qemu_invalidate_map_cache(void)
|
2008-08-18 00:24:29 +02:00
|
|
|
#define mapcache_lock() ((void)0)
|
|
|
|
#define mapcache_unlock() ((void)0)
|
2008-07-19 01:04:37 +02:00
|
|
|
|
2008-08-18 00:24:29 +02:00
|
|
|
+/* Reason for xen_pause_requested */
|
2008-07-19 01:04:37 +02:00
|
|
|
+enum {
|
|
|
|
+ SUSPEND_SAVEVM = 1,
|
|
|
|
+ SUSPEND_SNAPSHOT = 2
|
|
|
|
+};
|
|
|
|
+
|
2008-08-18 00:24:29 +02:00
|
|
|
+/* xen-vl-extra.c */
|
2008-07-19 01:04:37 +02:00
|
|
|
+int save_disk_snapshots(const char* name);
|
|
|
|
+
|
2008-08-18 00:24:29 +02:00
|
|
|
/* helper2.c */
|
|
|
|
extern long time_offset;
|
|
|
|
void timeoffset_get(void);
|
2009-05-04 18:38:09 +02:00
|
|
|
@@ -68,6 +77,7 @@ int xenstore_fd(void);
|
2008-11-21 15:57:01 +01:00
|
|
|
void xenstore_process_event(void *opaque);
|
2009-05-04 18:38:09 +02:00
|
|
|
void xenstore_record_dm(const char *subpath, const char *state);
|
|
|
|
void xenstore_record_dm_state(const char *state);
|
2010-03-02 01:46:56 +01:00
|
|
|
+void xenstore_record_dm_error(const char *errmsg);
|
2008-11-21 15:57:01 +01:00
|
|
|
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);
|
2010-03-01 16:05:50 +01:00
|
|
|
Index: xen-4.0.0-testing/tools/ioemu-remote/xenstore.c
|
|
|
|
===================================================================
|
|
|
|
--- xen-4.0.0-testing.orig/tools/ioemu-remote/xenstore.c
|
|
|
|
+++ xen-4.0.0-testing/tools/ioemu-remote/xenstore.c
|
2010-01-16 01:12:54 +01:00
|
|
|
@@ -17,6 +17,7 @@
|
2008-08-18 00:24:29 +02:00
|
|
|
|
|
|
|
#include "exec-all.h"
|
|
|
|
#include "sysemu.h"
|
|
|
|
+#include "qemu-xen.h"
|
|
|
|
|
2010-03-02 01:46:56 +01:00
|
|
|
#include "console.h"
|
2008-08-18 00:24:29 +02:00
|
|
|
#include "hw.h"
|
2010-03-02 01:46:56 +01:00
|
|
|
@@ -839,6 +840,7 @@ static void xenstore_process_dm_command_
|
2008-08-18 00:24:29 +02:00
|
|
|
{
|
2008-07-19 01:04:37 +02:00
|
|
|
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) {
|
2010-03-02 01:46:56 +01:00
|
|
|
@@ -854,7 +856,18 @@ static void xenstore_process_dm_command_
|
2010-01-16 01:12:54 +01:00
|
|
|
|
2008-07-19 01:04:37 +02:00
|
|
|
if (!strncmp(command, "save", len)) {
|
|
|
|
fprintf(logfile, "dm-command: pause and save state\n");
|
2008-08-18 00:24:29 +02:00
|
|
|
- xen_pause_requested = 1;
|
|
|
|
+ xen_pause_requested = SUSPEND_SAVEVM;
|
2008-07-19 01:04:37 +02:00
|
|
|
+ } else if (!strncmp(command, "snapshot", len)) {
|
|
|
|
+ fprintf(logfile, "dm-command: pause and snapshot disks\n");
|
2008-08-18 00:24:29 +02:00
|
|
|
+ xen_pause_requested = SUSPEND_SNAPSHOT;
|
2008-07-19 01:04:37 +02:00
|
|
|
+
|
|
|
|
+ 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");
|
2008-08-18 00:24:29 +02:00
|
|
|
xen_pause_requested = 0;
|
2010-03-02 01:46:56 +01:00
|
|
|
@@ -987,6 +1000,13 @@ void xenstore_record_dm_state(const char
|
2008-11-21 15:57:01 +01:00
|
|
|
xenstore_record_dm("state", state);
|
|
|
|
}
|
|
|
|
|
2010-03-02 01:46:56 +01:00
|
|
|
+void xenstore_record_dm_error(const char *errmsg)
|
2008-11-21 15:57:01 +01:00
|
|
|
+{
|
|
|
|
+ fprintf(logfile, "%s\n", errmsg);
|
|
|
|
+ xenstore_record_dm("error", errmsg);
|
|
|
|
+ xenstore_record_dm_state("error");
|
|
|
|
+}
|
|
|
|
+
|
2010-03-02 01:46:56 +01:00
|
|
|
static void xenstore_process_media_change_event(char **vec)
|
2008-11-21 15:57:01 +01:00
|
|
|
{
|
|
|
|
char *media_present = NULL;
|