]> git.proxmox.com Git - qemu.git/blobdiff - migration.c
Purge migration of (almost) everything to do with monitors
[qemu.git] / migration.c
index 4b175668574b37d934a0643e06cfba82b8162ffc..b21b2df50400c4100e8523fb5900baeebcec97a0 100644 (file)
@@ -9,6 +9,8 @@
  * This work is licensed under the terms of the GNU GPL, version 2.  See
  * the COPYING file in the top-level directory.
  *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
  */
 
 #include "qemu-common.h"
@@ -89,6 +91,9 @@ void process_incoming_migration(QEMUFile *f)
     qemu_announce_self();
     DPRINTF("successfully loaded vm state\n");
 
+    /* Make sure all file formats flush their mutable metadata */
+    bdrv_invalidate_cache_all();
+
     if (autostart) {
         vm_start();
     } else {
@@ -155,7 +160,6 @@ MigrationInfo *qmp_query_migrate(Error **errp)
 
 static void migrate_fd_monitor_suspend(MigrationState *s, Monitor *mon)
 {
-    s->mon = mon;
     if (monitor_suspend(mon) == 0) {
         DPRINTF("suspending monitor\n");
     } else {
@@ -172,9 +176,7 @@ static int migrate_fd_cleanup(MigrationState *s)
 
     if (s->file) {
         DPRINTF("closing file\n");
-        if (qemu_fclose(s->file) != 0) {
-            ret = -1;
-        }
+        ret = qemu_fclose(s->file);
         s->file = NULL;
     } else {
         if (s->mon) {
@@ -256,7 +258,7 @@ static void migrate_fd_put_ready(void *opaque)
     }
 
     DPRINTF("iterate\n");
-    ret = qemu_savevm_state_iterate(s->mon, s->file);
+    ret = qemu_savevm_state_iterate(s->file);
     if (ret < 0) {
         migrate_fd_error(s);
     } else if (ret == 1) {
@@ -265,7 +267,7 @@ static void migrate_fd_put_ready(void *opaque)
         DPRINTF("done iterating\n");
         vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
 
-        if (qemu_savevm_state_complete(s->mon, s->file) < 0) {
+        if (qemu_savevm_state_complete(s->file) < 0) {
             migrate_fd_error(s);
         } else {
             migrate_fd_completed(s);
@@ -287,7 +289,7 @@ static void migrate_fd_cancel(MigrationState *s)
 
     s->state = MIG_STATE_CANCELLED;
     notifier_list_notify(&migration_state_notifiers, s);
-    qemu_savevm_state_cancel(s->mon, s->file);
+    qemu_savevm_state_cancel(s->file);
 
     migrate_fd_cleanup(s);
 }
@@ -333,7 +335,7 @@ void add_migration_state_change_notifier(Notifier *notify)
 
 void remove_migration_state_change_notifier(Notifier *notify)
 {
-    notifier_list_remove(&migration_state_notifiers, notify);
+    notifier_remove(notify);
 }
 
 bool migration_is_active(MigrationState *s)
@@ -365,7 +367,7 @@ void migrate_fd_connect(MigrationState *s)
                                       migrate_fd_close);
 
     DPRINTF("beginning savevm\n");
-    ret = qemu_savevm_state_begin(s->mon, s->file, s->blk, s->shared);
+    ret = qemu_savevm_state_begin(s->file, s->blk, s->shared);
     if (ret < 0) {
         DPRINTF("failed, %d\n", ret);
         migrate_fd_error(s);
@@ -383,7 +385,12 @@ static MigrationState *migrate_init(Monitor *mon, int detach, int blk, int inc)
     s->bandwidth_limit = bandwidth_limit;
     s->blk = blk;
     s->shared = inc;
-    s->mon = NULL;
+
+    /* s->mon is used for two things:
+       - pass fd in fd migration
+       - suspend/resume monitor for not detached migration
+    */
+    s->mon = mon;
     s->bandwidth_limit = bandwidth_limit;
     s->state = MIG_STATE_SETUP;
 
@@ -394,6 +401,18 @@ static MigrationState *migrate_init(Monitor *mon, int detach, int blk, int inc)
     return s;
 }
 
+static GSList *migration_blockers;
+
+void migrate_add_blocker(Error *reason)
+{
+    migration_blockers = g_slist_prepend(migration_blockers, reason);
+}
+
+void migrate_del_blocker(Error *reason)
+{
+    migration_blockers = g_slist_remove(migration_blockers, reason);
+}
+
 int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     MigrationState *s = migrate_get_current();
@@ -413,6 +432,12 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
         return -1;
     }
 
+    if (migration_blockers) {
+        Error *err = migration_blockers->data;
+        qerror_report_err(err);
+        return -1;
+    }
+
     s = migrate_init(mon, detach, blk, inc);
 
     if (strstart(uri, "tcp:", &p)) {
@@ -435,41 +460,35 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
         return ret;
     }
 
+    if (detach) {
+        s->mon = NULL;
+    }
+
     notifier_list_notify(&migration_state_notifiers, s);
     return 0;
 }
 
-int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_migrate_cancel(Error **errp)
 {
     migrate_fd_cancel(migrate_get_current());
-    return 0;
 }
 
-int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_migrate_set_speed(int64_t value, Error **errp)
 {
-    int64_t d;
     MigrationState *s;
 
-    d = qdict_get_int(qdict, "value");
-    if (d < 0) {
-        d = 0;
+    if (value < 0) {
+        value = 0;
     }
 
     s = migrate_get_current();
-    s->bandwidth_limit = d;
+    s->bandwidth_limit = value;
     qemu_file_set_rate_limit(s->file, s->bandwidth_limit);
-
-    return 0;
 }
 
-int do_migrate_set_downtime(Monitor *mon, const QDict *qdict,
-                            QObject **ret_data)
+void qmp_migrate_set_downtime(double value, Error **errp)
 {
-    double d;
-
-    d = qdict_get_double(qdict, "value") * 1e9;
-    d = MAX(0, MIN(UINT64_MAX, d));
-    max_downtime = (uint64_t)d;
-
-    return 0;
+    value *= 1e9;
+    value = MAX(0, MIN(UINT64_MAX, value));
+    max_downtime = (uint64_t)value;
 }