QEMU_CAPS_SEAMLESS_MIGRATION capability says QEMU supports SPICE_MIGRATE_COMPLETED event. Thus we can just drop all code which polls query-spice and replace it with waiting for the event. Signed-off-by: Jiri Denemark <jdenemar@xxxxxxxxxx> --- Notes: ACKed in version 2 Version 3: - no change Version 2: - new patch src/qemu/qemu_domain.c | 1 + src/qemu/qemu_domain.h | 1 + src/qemu/qemu_migration.c | 38 ++++++++++------------------------ src/qemu/qemu_monitor.c | 10 --------- src/qemu/qemu_monitor.h | 2 -- src/qemu/qemu_monitor_json.c | 49 -------------------------------------------- src/qemu/qemu_process.c | 28 +++++++++++++++++++++++++ tests/qemumonitorjsontest.c | 40 ------------------------------------ 8 files changed, 41 insertions(+), 128 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 25fa8d3..c9bdf6b 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -170,6 +170,7 @@ qemuDomainObjResetAsyncJob(qemuDomainObjPrivatePtr priv) job->mask = QEMU_JOB_DEFAULT_MASK; job->dump_memory_only = false; job->abortJob = false; + job->spiceMigrated = false; VIR_FREE(job->current); } diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index a3c5015..54e1e7b 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -136,6 +136,7 @@ struct qemuDomainJobObj { qemuDomainJobInfoPtr current; /* async job progress data */ qemuDomainJobInfoPtr completed; /* statistics data of a recently completed job */ bool abortJob; /* abort of the job requested */ + bool spiceMigrated; /* spice migration completed */ }; typedef void (*qemuDomainCleanupCallback)(virQEMUDriverPtr driver, diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index d82a5ba..d5a9dea 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -2390,45 +2390,29 @@ qemuMigrationSetPinAll(virQEMUDriverPtr driver, } static int -qemuMigrationWaitForSpice(virQEMUDriverPtr driver, - virDomainObjPtr vm) +qemuMigrationWaitForSpice(virDomainObjPtr vm) { qemuDomainObjPrivatePtr priv = vm->privateData; bool wait_for_spice = false; - bool spice_migrated = false; size_t i = 0; - int rc; - if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SEAMLESS_MIGRATION)) { - for (i = 0; i < vm->def->ngraphics; i++) { - if (vm->def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) { - wait_for_spice = true; - break; - } + if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SEAMLESS_MIGRATION)) + return 0; + + for (i = 0; i < vm->def->ngraphics; i++) { + if (vm->def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) { + wait_for_spice = true; + break; } } 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 }; - - if (qemuDomainObjEnterMonitorAsync(driver, vm, - QEMU_ASYNC_JOB_MIGRATION_OUT) < 0) + while (!priv->job.spiceMigrated && !priv->job.abortJob) { + if (virDomainObjWait(vm) < 0) return -1; - - rc = qemuMonitorGetSpiceMigrationStatus(priv->mon, &spice_migrated); - if (qemuDomainObjExitMonitor(driver, vm) < 0) - return -1; - if (rc < 0) - return -1; - virObjectUnlock(vm); - nanosleep(&ts, NULL); - virObjectLock(vm); } - return 0; } @@ -3602,7 +3586,7 @@ qemuMigrationConfirmPhase(virQEMUDriverPtr driver, 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); + qemuMigrationWaitForSpice(vm); qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_MIGRATED, VIR_QEMU_PROCESS_STOP_MIGRATED); diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index b7de846..94b0007 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2117,16 +2117,6 @@ qemuMonitorGetMigrationStatus(qemuMonitorPtr mon, int -qemuMonitorGetSpiceMigrationStatus(qemuMonitorPtr mon, - bool *spice_migrated) -{ - QEMU_CHECK_MONITOR_JSON(mon); - - return qemuMonitorJSONGetSpiceMigrationStatus(mon, spice_migrated); -} - - -int qemuMonitorMigrateToFd(qemuMonitorPtr mon, unsigned int flags, int fd) diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index a29c505..1afc344 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -498,8 +498,6 @@ struct _qemuMonitorMigrationStatus { int qemuMonitorGetMigrationStatus(qemuMonitorPtr mon, qemuMonitorMigrationStatusPtr status); -int qemuMonitorGetSpiceMigrationStatus(qemuMonitorPtr mon, - bool *spice_migrated); typedef enum { QEMU_MONITOR_MIGRATION_CAPS_XBZRLE, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 04ae339..0ba549e 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2684,55 +2684,6 @@ int qemuMonitorJSONGetMigrationStatus(qemuMonitorPtr mon, } -static int -qemuMonitorJSONSpiceGetMigrationStatusReply(virJSONValuePtr reply, - bool *spice_migrated) -{ - virJSONValuePtr ret; - - if (!(ret = virJSONValueObjectGet(reply, "return"))) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("query-spice reply was missing return data")); - return -1; - } - - if (virJSONValueObjectGetBoolean(ret, "migrated", spice_migrated) < 0) { - /* Deliberately don't report error here as we are - * probably dealing with older qemu which doesn't - * report this yet. Pretend spice is migrated. */ - *spice_migrated = true; - } - - return 0; -} - - -int qemuMonitorJSONGetSpiceMigrationStatus(qemuMonitorPtr mon, - bool *spice_migrated) -{ - int ret; - virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-spice", - NULL); - virJSONValuePtr reply = NULL; - - if (!cmd) - return -1; - - ret = qemuMonitorJSONCommand(mon, cmd, &reply); - - if (ret == 0) - ret = qemuMonitorJSONCheckError(cmd, reply); - - if (ret == 0) - ret = qemuMonitorJSONSpiceGetMigrationStatusReply(reply, - spice_migrated); - - virJSONValueFree(cmd); - virJSONValueFree(reply); - return ret; -} - - int qemuMonitorJSONMigrate(qemuMonitorPtr mon, unsigned int flags, const char *uri) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 5be0002..ba84182 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -1481,6 +1481,33 @@ qemuProcessHandleSerialChanged(qemuMonitorPtr mon ATTRIBUTE_UNUSED, } +static int +qemuProcessHandleSpiceMigrated(qemuMonitorPtr mon ATTRIBUTE_UNUSED, + virDomainObjPtr vm, + void *opaque ATTRIBUTE_UNUSED) +{ + qemuDomainObjPrivatePtr priv; + + virObjectLock(vm); + + VIR_DEBUG("Spice migration completed for domain %p %s", + vm, vm->def->name); + + priv = vm->privateData; + if (priv->job.asyncJob != QEMU_ASYNC_JOB_MIGRATION_OUT) { + VIR_DEBUG("got SPICE_MIGRATE_COMPLETED event without a migration job"); + goto cleanup; + } + + priv->job.spiceMigrated = true; + virDomainObjSignal(vm); + + cleanup: + virObjectUnlock(vm); + return 0; +} + + static qemuMonitorCallbacks monitorCallbacks = { .eofNotify = qemuProcessHandleMonitorEOF, .errorNotify = qemuProcessHandleMonitorError, @@ -1504,6 +1531,7 @@ static qemuMonitorCallbacks monitorCallbacks = { .domainDeviceDeleted = qemuProcessHandleDeviceDeleted, .domainNicRxFilterChanged = qemuProcessHandleNicRxFilterChanged, .domainSerialChange = qemuProcessHandleSerialChanged, + .domainSpiceMigrated = qemuProcessHandleSpiceMigrated, }; static int diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index 0f82fd8..0623275 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -1706,45 +1706,6 @@ testQemuMonitorJSONqemuMonitorJSONGetMigrationStatus(const void *data) } static int -testQemuMonitorJSONqemuMonitorJSONGetSpiceMigrationStatus(const void *data) -{ - virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data; - qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt); - int ret = -1; - bool spiceMigrated; - - if (!test) - return -1; - - if (qemuMonitorTestAddItem(test, "query-spice", - "{" - " \"return\": {" - " \"migrated\": true," - " \"enabled\": false," - " \"mouse-mode\": \"client\"" - " }," - " \"id\": \"libvirt-14\"" - "}") < 0) - goto cleanup; - - if (qemuMonitorJSONGetSpiceMigrationStatus(qemuMonitorTestGetMonitor(test), - &spiceMigrated) < 0) - goto cleanup; - - if (!spiceMigrated) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "Invalid spice migration status: %d, expecting 1", - spiceMigrated); - goto cleanup; - } - - ret = 0; - cleanup: - qemuMonitorTestFree(test); - return ret; -} - -static int testHashEqualChardevInfo(const void *value1, const void *value2) { const qemuMonitorChardevInfo *info1 = value1; @@ -2400,7 +2361,6 @@ mymain(void) DO_TEST(qemuMonitorJSONGetBlockStatsInfo); DO_TEST(qemuMonitorJSONGetMigrationCacheSize); DO_TEST(qemuMonitorJSONGetMigrationStatus); - DO_TEST(qemuMonitorJSONGetSpiceMigrationStatus); DO_TEST(qemuMonitorJSONGetChardevInfo); DO_TEST(qemuMonitorJSONSetBlockIoThrottle); DO_TEST(qemuMonitorJSONGetTargetArch); -- 2.4.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list