]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu_migration: Move waiting for SPICE migration
authorMichal Privoznik <mprivozn@redhat.com>
Mon, 10 Jun 2013 13:35:03 +0000 (15:35 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Tue, 18 Jun 2013 12:32:52 +0000 (14:32 +0200)
Currently, we wait for SPICE to migrate in the very same loop where we
wait for qemu to migrate. This has a disadvantage of slowing seamless
migration down. One one hand, we should not kill the domain until all
SPICE data has been migrated.  On the other hand, there is no need to
wait in the very same loop and hence slowing down 'cont' on the
destination. For instance, if users are watching a movie, they can
experience the movie to be stopped for a couple of seconds, as
processors are not running nor on src nor on dst as libvirt waits for
SPICE to migrate. We should move the waiting phase to migration CONFIRM
phase.

src/qemu/qemu_migration.c

index 48e0d44a41be83d2f7396fe8419099623bf1507f..7d3b1859f39eafbeb2077172b385593b066a5c06 100644 (file)
@@ -1592,6 +1592,40 @@ cleanup:
     return ret;
 }
 
+static int
+qemuMigrationWaitForSpice(virQEMUDriverPtr driver,
+                          virDomainObjPtr vm)
+{
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+    bool wait_for_spice = false;
+    bool spice_migrated = false;
+
+    if (vm->def->ngraphics == 1 &&
+        vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE &&
+        virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SEAMLESS_MIGRATION))
+        wait_for_spice = true;
+
+    if (!wait_for_spice)
+        return 0;
+
+    while (!spice_migrated) {
+        /* Poll every 50ms for progress & to allow cancellation */
+        struct timespec ts = { .tv_sec = 0, .tv_nsec = 50 * 1000 * 1000ull };
+
+        qemuDomainObjEnterMonitor(driver, vm);
+        if (qemuMonitorGetSpiceMigrationStatus(priv->mon,
+                                               &spice_migrated) < 0) {
+            qemuDomainObjExitMonitor(driver, vm);
+            return -1;
+        }
+        qemuDomainObjExitMonitor(driver, vm);
+        virObjectUnlock(vm);
+        nanosleep(&ts, NULL);
+        virObjectLock(vm);
+    }
+
+    return 0;
+}
 
 static int
 qemuMigrationUpdateJobStatus(virQEMUDriverPtr driver,
@@ -1601,19 +1635,10 @@ qemuMigrationUpdateJobStatus(virQEMUDriverPtr driver,
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     int ret;
-    bool wait_for_spice = false;
-    bool spice_migrated = false;
     qemuMonitorMigrationStatus status;
 
     memset(&status, 0, sizeof(status));
 
-    /* If guest uses SPICE and supports seamles_migration we have to hold up
-     * migration finish until SPICE server transfers its data */
-    if (vm->def->ngraphics == 1 &&
-        vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE &&
-        virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SEAMLESS_MIGRATION))
-        wait_for_spice = true;
-
     ret = qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob);
     if (ret < 0) {
         /* Guest already exited; nothing further to update.  */
@@ -1621,13 +1646,6 @@ qemuMigrationUpdateJobStatus(virQEMUDriverPtr driver,
     }
     ret = qemuMonitorGetMigrationStatus(priv->mon, &status);
 
-    /* If qemu says migrated, check spice */
-    if (wait_for_spice &&
-        ret == 0 &&
-        status.status == QEMU_MONITOR_MIGRATION_STATUS_COMPLETED)
-        ret = qemuMonitorGetSpiceMigrationStatus(priv->mon,
-                                                 &spice_migrated);
-
     qemuDomainObjExitMonitor(driver, vm);
 
     priv->job.status = status;
@@ -1667,8 +1685,7 @@ qemuMigrationUpdateJobStatus(virQEMUDriverPtr driver,
         break;
 
     case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED:
-        if ((wait_for_spice && spice_migrated) || (!wait_for_spice))
-            priv->job.info.type = VIR_DOMAIN_JOB_COMPLETED;
+        priv->job.info.type = VIR_DOMAIN_JOB_COMPLETED;
         ret = 0;
         break;
 
@@ -4151,6 +4168,10 @@ int qemuMigrationConfirm(virQEMUDriverPtr driver,
      * domain object, but if no, resume CPUs
      */
     if (retcode == 0) {
+        /* If guest uses SPICE and supports seamless migration we have to hold
+         * up domain shutdown until SPICE server transfers its data */
+        qemuMigrationWaitForSpice(driver, vm);
+
         qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_MIGRATED,
                         VIR_QEMU_PROCESS_STOP_MIGRATED);
         virDomainAuditStop(vm, "migrated");