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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list