qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [MIGRATION_TO_FILE_ALTERNATIVE] savevm/loadvm to/from a fil


From: Uri Lublin
Subject: [Qemu-devel] [MIGRATION_TO_FILE_ALTERNATIVE] savevm/loadvm to/from a file
Date: Tue, 20 Jan 2009 13:35:17 +0200

Sometimes we do not want to save VM state internally (within the image).
For example raw images (and any other non qcow images) are not capable
of savevm'ing.

This patch enables saving/loading the VM state in/from a file.

It introduces two monitor commands savevm_file and loadvm_file (should I just 
add flags or add prefix to savevm/loadvm ?).
When saving VM state, upon successful operation, the VM is left in stopped mode
(such that it does not change the disk image).
When loading VM state, upon a failure, the VM is left in stopped mode; The user
or a management-app should send a quit command, as otherwise the VM state may be
inconsistent.

Signed-off-by: Uri Lublin <address@hidden>
---
 monitor.c |    4 ++++
 savevm.c  |   58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 sysemu.h  |    2 ++
 3 files changed, 64 insertions(+), 0 deletions(-)

diff --git a/monitor.c b/monitor.c
index 7ff9890..02274bc 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1454,6 +1454,10 @@ static const term_cmd_t term_cmds[] = {
       "tag|id", "restore a VM snapshot from its tag or id" },
     { "delvm", "s", do_delvm,
       "tag|id", "delete a VM snapshot from its tag or id" },
+    { "savevm_file", "F", do_savevm_file,
+      "filename", "save a VM state in a file." },
+    { "loadvm_file", "F", do_loadvm_file,
+      "filename", "load a VM state from a file" },
     { "stop", "", do_stop,
       "", "stop emulation", },
     { "c|cont", "", do_cont,
diff --git a/savevm.c b/savevm.c
index 729e849..98f73ce 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1114,6 +1114,37 @@ void do_savevm(const char *name)
         vm_start();
 }
 
+void do_savevm_file(const char *filename)
+{
+    int saved_vm_running = vm_running;
+    int ret;
+    QEMUFile *f;
+
+    umask(00600); /* rw for user only */
+
+    /* save the VM state */
+    f = qemu_fopen(filename, "wb");
+    if (!f) {
+        term_printf("Could not open VM state file %s\n", filename);
+        return;
+    }
+    qemu_aio_flush();
+    vm_stop(0);
+    ret = qemu_savevm_state(f);
+    qemu_fclose(f);
+    if (ret < 0) {
+        term_printf("Error %d while writing VM\n", ret);
+        unlink(filename);
+        /* continue only upon failure */
+        if (saved_vm_running)
+            vm_start();
+    }
+    else {
+        term_printf("completed successfully savevm_file %s\n", filename);
+    }
+}
+
+
 void do_loadvm(const char *name)
 {
     BlockDriverState *bs, *bs1;
@@ -1190,6 +1221,33 @@ void do_loadvm(const char *name)
         vm_start();
 }
 
+void do_loadvm_file(const char *filename)
+{
+    int ret;
+    QEMUFile *f;
+
+    f = qemu_fopen(filename, "rb");
+    if (!f) {
+        term_printf("Could not open VM state file %s\n", filename);
+        return;
+    }
+
+    /* Flush all IO requests so they don't interfere with the new state.  */
+    qemu_aio_flush();
+    vm_stop(0);
+
+    ret = qemu_loadvm_state(f);
+    qemu_fclose(f);
+    if (ret < 0) {
+        term_printf("Error %d while writing VM\n", ret);
+    }
+    else {
+        /* continue only upon success */
+        term_printf("completed successfully loadvm_file %s\n", filename);
+        vm_start();
+    }
+}
+
 void do_delvm(const char *name)
 {
     BlockDriverState *bs, *bs1;
diff --git a/sysemu.h b/sysemu.h
index 56eb9b3..f27058b 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -47,6 +47,8 @@ void do_savevm(const char *name);
 void do_loadvm(const char *name);
 void do_delvm(const char *name);
 void do_info_snapshots(void);
+void do_savevm_file(const char *filename);
+void do_loadvm_file(const char *filename);
 
 void qemu_announce_self(void);
 
-- 
1.6.0.6





reply via email to

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