a7b9285
From 907358d71215fdc486c6e70de9b16cfefc88303b Mon Sep 17 00:00:00 2001
Alon Levy 408bdb5
From: Paolo Bonzini <pbonzini@redhat.com>
Alon Levy 408bdb5
Date: Fri, 22 Feb 2013 17:36:18 +0100
a7b9285
Subject: [PATCH] migration: do not nest flushing of device data
Alon Levy 408bdb5
Alon Levy 408bdb5
Completion of migration is currently done with a "nested" loop that
Alon Levy 408bdb5
invokes buffered_flush: migrate_fd_completed is called by
Alon Levy 408bdb5
buffered_file_thread, which calls migrate_fd_cleanup, which calls
Alon Levy 408bdb5
buffered_close (via qemu_fclose), which flushes the buffer.
Alon Levy 408bdb5
Alon Levy 408bdb5
Simplify this, by reusing the buffered_flush call of buffered_file_thread.
Alon Levy 408bdb5
Then if qemu_savevm_state_complete was called, and the buffer is empty
Alon Levy 408bdb5
(including the QEMUFile buffer, for which we need the previous patch), we
Alon Levy 408bdb5
are done.
Alon Levy 408bdb5
Alon Levy 408bdb5
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Alon Levy 408bdb5
Reviewed-by: Juan Quintela <quintela@redhat.com>
Alon Levy 408bdb5
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Alon Levy 408bdb5
Signed-off-by: Juan Quintela <quintela@redhat.com>
a7b9285
(cherry picked from commit a3fa1d78cbae2259491b17689812edcb643a3b30)
Alon Levy 408bdb5
---
Alon Levy 408bdb5
 migration.c | 55 ++++++++++++++++++++++++-------------------------------
Alon Levy 408bdb5
 1 file changed, 24 insertions(+), 31 deletions(-)
Alon Levy 408bdb5
Alon Levy 408bdb5
diff --git a/migration.c b/migration.c
Alon Levy 408bdb5
index 41a592c..57fceb6d 100644
Alon Levy 408bdb5
--- a/migration.c
Alon Levy 408bdb5
+++ b/migration.c
Alon Levy 408bdb5
@@ -262,41 +262,34 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
Alon Levy 408bdb5
 
Alon Levy 408bdb5
 static void migrate_fd_cleanup(MigrationState *s)
Alon Levy 408bdb5
 {
Alon Levy 408bdb5
-    int ret = 0;
Alon Levy 408bdb5
-
Alon Levy 408bdb5
     if (s->file) {
Alon Levy 408bdb5
         DPRINTF("closing file\n");
Alon Levy 408bdb5
-        ret = qemu_fclose(s->file);
Alon Levy 408bdb5
+        qemu_fclose(s->file);
Alon Levy 408bdb5
         s->file = NULL;
Alon Levy 408bdb5
     }
Alon Levy 408bdb5
 
Alon Levy 408bdb5
     assert(s->fd == -1);
Alon Levy 408bdb5
-    if (ret < 0 && s->state == MIG_STATE_ACTIVE) {
Alon Levy 408bdb5
-        s->state = MIG_STATE_ERROR;
Alon Levy 408bdb5
-    }
Alon Levy 408bdb5
+    assert(s->state != MIG_STATE_ACTIVE);
Alon Levy 408bdb5
 
Alon Levy 408bdb5
-    if (s->state != MIG_STATE_ACTIVE) {
Alon Levy 408bdb5
+    if (s->state != MIG_STATE_COMPLETED) {
Alon Levy 408bdb5
         qemu_savevm_state_cancel();
Alon Levy 408bdb5
     }
Alon Levy 408bdb5
+
Alon Levy 408bdb5
+    notifier_list_notify(&migration_state_notifiers, s);
Alon Levy 408bdb5
 }
Alon Levy 408bdb5
 
Alon Levy 408bdb5
 void migrate_fd_error(MigrationState *s)
Alon Levy 408bdb5
 {
Alon Levy 408bdb5
     DPRINTF("setting error state\n");
Alon Levy 408bdb5
     s->state = MIG_STATE_ERROR;
Alon Levy 408bdb5
-    notifier_list_notify(&migration_state_notifiers, s);
Alon Levy 408bdb5
     migrate_fd_cleanup(s);
Alon Levy 408bdb5
 }
Alon Levy 408bdb5
 
Alon Levy 408bdb5
 static void migrate_fd_completed(MigrationState *s)
Alon Levy 408bdb5
 {
Alon Levy 408bdb5
     DPRINTF("setting completed state\n");
Alon Levy 408bdb5
+    s->state = MIG_STATE_COMPLETED;
Alon Levy 408bdb5
     migrate_fd_cleanup(s);
Alon Levy 408bdb5
-    if (s->state == MIG_STATE_ACTIVE) {
Alon Levy 408bdb5
-        s->state = MIG_STATE_COMPLETED;
Alon Levy 408bdb5
-        runstate_set(RUN_STATE_POSTMIGRATE);
Alon Levy 408bdb5
-    }
Alon Levy 408bdb5
-    notifier_list_notify(&migration_state_notifiers, s);
Alon Levy 408bdb5
 }
Alon Levy 408bdb5
 
Alon Levy 408bdb5
 static ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data,
Alon Levy 408bdb5
@@ -326,8 +319,6 @@ static void migrate_fd_cancel(MigrationState *s)
Alon Levy 408bdb5
     DPRINTF("cancelling migration\n");
Alon Levy 408bdb5
 
Alon Levy 408bdb5
     s->state = MIG_STATE_CANCELLED;
Alon Levy 408bdb5
-    notifier_list_notify(&migration_state_notifiers, s);
Alon Levy 408bdb5
-
Alon Levy 408bdb5
     migrate_fd_cleanup(s);
Alon Levy 408bdb5
 }
Alon Levy 408bdb5
 
Alon Levy 408bdb5
@@ -592,10 +583,6 @@ static int buffered_close(void *opaque)
Alon Levy 408bdb5
 
Alon Levy 408bdb5
     DPRINTF("closing\n");
Alon Levy 408bdb5
 
Alon Levy 408bdb5
-    s->xfer_limit = INT_MAX;
Alon Levy 408bdb5
-    while (!qemu_file_get_error(s->file) && s->buffer_size) {
Alon Levy 408bdb5
-        buffered_flush(s);
Alon Levy 408bdb5
-    }
Alon Levy 408bdb5
     return migrate_fd_close(s);
Alon Levy 408bdb5
 }
Alon Levy 408bdb5
 
Alon Levy 408bdb5
@@ -658,6 +645,8 @@ static void *buffered_file_thread(void *opaque)
Alon Levy 408bdb5
     int64_t initial_time = qemu_get_clock_ms(rt_clock);
Alon Levy 408bdb5
     int64_t sleep_time = 0;
Alon Levy 408bdb5
     int64_t max_size = 0;
Alon Levy 408bdb5
+    int64_t start_time = initial_time;
Alon Levy 408bdb5
+    bool old_vm_running = false;
Alon Levy 408bdb5
     bool last_round = false;
Alon Levy 408bdb5
 
Alon Levy 408bdb5
     qemu_mutex_lock_iothread();
Alon Levy 408bdb5
@@ -675,23 +664,13 @@ static void *buffered_file_thread(void *opaque)
Alon Levy 408bdb5
             if (pending_size && pending_size >= max_size) {
Alon Levy 408bdb5
                 qemu_savevm_state_iterate(s->file);
Alon Levy 408bdb5
             } else {
Alon Levy 408bdb5
-                int old_vm_running = runstate_is_running();
Alon Levy 408bdb5
-                int64_t start_time, end_time;
Alon Levy 408bdb5
-
Alon Levy 408bdb5
                 DPRINTF("done iterating\n");
Alon Levy 408bdb5
                 start_time = qemu_get_clock_ms(rt_clock);
Alon Levy 408bdb5
                 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
Alon Levy 408bdb5
+                old_vm_running = runstate_is_running();
Alon Levy 408bdb5
                 vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
Alon Levy 408bdb5
+                s->xfer_limit = INT_MAX;
Alon Levy 408bdb5
                 qemu_savevm_state_complete(s->file);
Alon Levy 408bdb5
-                migrate_fd_completed(s);
Alon Levy 408bdb5
-                end_time = qemu_get_clock_ms(rt_clock);
Alon Levy 408bdb5
-                s->total_time = end_time - s->total_time;
Alon Levy 408bdb5
-                s->downtime = end_time - start_time;
Alon Levy 408bdb5
-                if (s->state != MIG_STATE_COMPLETED) {
Alon Levy 408bdb5
-                    if (old_vm_running) {
Alon Levy 408bdb5
-                        vm_start();
Alon Levy 408bdb5
-                    }
Alon Levy 408bdb5
-                }
Alon Levy 408bdb5
                 last_round = true;
Alon Levy 408bdb5
             }
Alon Levy 408bdb5
         }
Alon Levy 408bdb5
@@ -725,6 +704,20 @@ static void *buffered_file_thread(void *opaque)
Alon Levy 408bdb5
         qemu_mutex_lock_iothread();
Alon Levy 408bdb5
         if (qemu_file_get_error(s->file)) {
Alon Levy 408bdb5
             migrate_fd_error(s);
Alon Levy 408bdb5
+        } else if (last_round && s->buffer_size == 0) {
Alon Levy 408bdb5
+            migrate_fd_completed(s);
Alon Levy 408bdb5
+        }
Alon Levy 408bdb5
+    }
Alon Levy 408bdb5
+
Alon Levy 408bdb5
+    if (s->state == MIG_STATE_COMPLETED) {
Alon Levy 408bdb5
+        int64_t end_time = qemu_get_clock_ms(rt_clock);
Alon Levy 408bdb5
+        s->total_time = end_time - s->total_time;
Alon Levy 408bdb5
+        s->downtime = end_time - start_time;
Alon Levy 408bdb5
+        runstate_set(RUN_STATE_POSTMIGRATE);
Alon Levy 408bdb5
+    } else {
Alon Levy 408bdb5
+        if (old_vm_running) {
Alon Levy 408bdb5
+            assert(last_round);
Alon Levy 408bdb5
+            vm_start();
Alon Levy 408bdb5
         }
Alon Levy 408bdb5
     }
Alon Levy 408bdb5