qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 2/3] move vm stop/start to migrate_set_state


From: Paolo Bonzini
Subject: [Qemu-devel] [PATCH 2/3] move vm stop/start to migrate_set_state
Date: Thu, 9 Jul 2009 13:47:38 +0200

With this patch, the state machine grows a new state, COMPLETING.
This new state corresponds to the VM being stopped while migration
is finalized.  Stopping and starting the machine is driven
exclusively by the state machine mechanisms.

Two rare bugs are fixed.  The first is a race; the VM used to remain
stopped if a migration was canceled exactly in what corresponds
to the new COMPLETING state.  A bit worse is that if an error occurred
exactly during the final stage (for example due to disk full)
the VM was unconditionally restarted, even if it was paused before
the beginning of the migration.

---
 migration.c |   36 +++++++++++++++++++++++++-----------
 migration.h |    2 ++
 2 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/migration.c b/migration.c
index 5abce0c..96585dd 100644
--- a/migration.c
+++ b/migration.c
@@ -150,6 +150,11 @@ void do_info_migrate(Monitor *mon)
             monitor_printf(mon, "remaining ram: %" PRIu64 " kbytes\n", 
ram_bytes_remaining() >> 10);
             monitor_printf(mon, "total ram: %" PRIu64 " kbytes\n", 
ram_bytes_total() >> 10);
             break;
+        case MIG_STATE_COMPLETING:
+            monitor_printf(mon, "completing\n");
+            monitor_printf(mon, "transferred ram: %" PRIu64 " kbytes\n", 
ram_bytes_transferred() >> 10);
+            monitor_printf(mon, "total ram: %" PRIu64 " kbytes\n", 
ram_bytes_total() >> 10);
+            break;
         case MIG_STATE_COMPLETED:
             monitor_printf(mon, "completed\n");
             break;
@@ -267,18 +272,13 @@ void migrate_fd_put_ready(void *opaque)
 
     dprintf("iterate\n");
     if (qemu_savevm_state_iterate(s->file) == 1) {
-        int state;
         dprintf("done iterating\n");
-        vm_stop(0);
 
-        bdrv_flush_all();
-        if ((qemu_savevm_state_complete(s->file)) < 0) {
-            vm_start();
-            state = MIG_STATE_ERROR;
-        } else {
-            state = MIG_STATE_COMPLETED;
-        }
-        migrate_set_state(&s->mig_state, state);
+        migrate_set_state(&s->mig_state, MIG_STATE_COMPLETING);
+        if ((qemu_savevm_state_complete(s->file)) < 0)
+            migrate_set_state(&s->mig_state, MIG_STATE_ERROR);
+        else
+            migrate_set_state(&s->mig_state, MIG_STATE_COMPLETED);
     }
 }
 
@@ -286,11 +286,25 @@ void migrate_set_state(MigrationState *s, int state)
 {
     s->state = state;
 
-    if (state != MIG_STATE_ACTIVE) {
+    switch (state) {
+    case MIG_STATE_COMPLETING:
+        s->save_vm_running = vm_running;
+        vm_stop(0);
+        bdrv_flush_all();
+        break;
+
+    case MIG_STATE_ACTIVE:
+        break;
+
+    default:
        s->cleanup (s);
         /* Don't resume monitor until we've flushed all of the buffers */
        if (s->mon_resume)
             monitor_resume(s->mon_resume);
+
+        if (s->save_vm_running && state != MIG_STATE_COMPLETED)
+           vm_start();
+        break;
     }
 }
 
diff --git a/migration.h b/migration.h
index 81ac361..c44bd75 100644
--- a/migration.h
+++ b/migration.h
@@ -20,6 +20,7 @@
 #define MIG_STATE_COMPLETED    0
 #define MIG_STATE_CANCELLED    1
 #define MIG_STATE_ACTIVE       2
+#define MIG_STATE_COMPLETING   3
 
 typedef struct MigrationState MigrationState;
 
@@ -27,6 +28,7 @@ struct MigrationState
 {
     Monitor *mon_resume;
     int state;
+    int save_vm_running;
 
     /* FIXME: add more accessors to print migration info */
     void (*cleanup)(MigrationState *s);
-- 
1.5.5.6






reply via email to

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