[libvirt] [PATCH 12/16] Make tunnelled migration honour job signals & update job status

Daniel P. Berrange berrange at redhat.com
Thu Apr 21 16:32:51 UTC 2011


Rewrite the doTunnelSendAll method so that it will process
job signals, and periodically ask QEMU for updated job status

* src/qemu/qemu_migration.c: Honour job signals/status during
  tunnelled migration
---
 src/qemu/qemu_migration.c |   72 +++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 67 insertions(+), 5 deletions(-)

diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 3cff4d7..4fb4c83 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -1299,11 +1299,16 @@ cleanup:
 
 #define TUNNEL_SEND_BUF_SIZE 65536
 
-static int doTunnelSendAll(virStreamPtr st,
+static int doTunnelSendAll(struct qemud_driver *driver,
+                           virDomainObjPtr vm,
+                           virStreamPtr st,
                            int sock)
 {
+    qemuDomainObjPrivatePtr priv = vm->privateData;
     char *buffer;
     int nbytes = TUNNEL_SEND_BUF_SIZE;
+    struct timeval now, then;
+    unsigned long long delta;
 
     if (VIR_ALLOC_N(buffer, TUNNEL_SEND_BUF_SIZE) < 0) {
         virReportOOMError();
@@ -1311,13 +1316,28 @@ static int doTunnelSendAll(virStreamPtr st,
         return -1;
     }
 
-    /* XXX should honour the 'resource' parameter here */
-    for (;;) {
+    if (gettimeofday(&then, NULL) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("cannot get time of day"));
+        virStreamAbort(st);
+        return -1;
+    }
+
+    priv->jobInfo.type = VIR_DOMAIN_JOB_UNBOUNDED;
+
+    while (priv->jobInfo.type == VIR_DOMAIN_JOB_UNBOUNDED) {
+        virDomainObjUnlock(vm);
+        qemuDriverUnlock(driver);
         nbytes = saferead(sock, buffer, nbytes);
+        qemuDriverLock(driver);
+        virDomainObjLock(vm);
+
         if (nbytes < 0) {
             virReportSystemError(errno, "%s",
                                  _("tunnelled migration failed to read from qemu"));
+            qemuDomainObjEnterRemoteWithDriver(driver, vm);
             virStreamAbort(st);
+            qemuDomainObjExitRemoteWithDriver(driver, vm);
             VIR_FREE(buffer);
             return -1;
         }
@@ -1325,19 +1345,56 @@ static int doTunnelSendAll(virStreamPtr st,
             /* EOF; get out of here */
             break;
 
+        qemuDomainObjEnterRemoteWithDriver(driver, vm);
         if (virStreamSend(st, buffer, nbytes) < 0) {
+            qemuDomainObjExitRemoteWithDriver(driver, vm);
             qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
                             _("Failed to write migration data to remote libvirtd"));
             VIR_FREE(buffer);
             return -1;
         }
+        qemuDomainObjExitRemoteWithDriver(driver, vm);
+
+        /* Process job signals on every loop */
+        if (qemuMigrationProcessJobSignals(driver, vm, "migration job") < 0) {
+            virStreamAbort(st);
+            return -1;
+        }
+
+
+        if (gettimeofday(&now, NULL) < 0) {
+            priv->jobInfo.type = VIR_DOMAIN_JOB_FAILED;
+            virReportSystemError(errno, "%s",
+                                 _("cannot get time of day"));
+            virStreamAbort(st);
+            return -1;
+        }
+
+        delta = ((now.tv_sec * 1000ull) + (now.tv_usec / 1000ull)) -
+            ((then.tv_sec * 1000ull) + (then.tv_usec / 1000ull));
+
+        /* Only update QEMU monitor status once a second, since we
+         * detect failure quickly enough already, via the EOF on the
+         * pipe we're reading from */
+        if (delta > 1000) {
+            then = now;
+
+            if (qemuMigrationUpdateJobStatus(driver, vm, "migration job") < 0) {
+                virStreamAbort(st);
+                return -1;
+            }
+        }
     }
 
     VIR_FREE(buffer);
 
-    if (virStreamFinish(st) < 0)
+    qemuDomainObjEnterRemoteWithDriver(driver, vm);
+    if (virStreamFinish(st) < 0) {
+        qemuDomainObjExitRemoteWithDriver(driver, vm);
         /* virStreamFinish set the error for us */
         return -1;
+    }
+    qemuDomainObjExitRemoteWithDriver(driver, vm);
 
     return 0;
 }
@@ -1434,6 +1491,11 @@ static int doTunnelMigrate(struct qemud_driver *driver,
 
     /*   3. start migration on source */
     qemuDomainObjEnterMonitorWithDriver(driver, vm);
+    if (resource > 0 &&
+        qemuMonitorSetMigrationSpeed(priv->mon, resource) < 0) {
+        qemuDomainObjExitMonitorWithDriver(driver, vm);
+        goto cleanup;
+    }
 
     if (flags & VIR_MIGRATE_NON_SHARED_DISK)
         background_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_DISK;
@@ -1495,7 +1557,7 @@ static int doTunnelMigrate(struct qemud_driver *driver,
         goto cancel;
     }
 
-    ret = doTunnelSendAll(st, client_sock);
+    ret = doTunnelSendAll(driver, vm, st, client_sock);
 
     if (ret == 0 &&
         qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, 0) < 0)
-- 
1.7.4.4




More information about the libvir-list mailing list