[PATCH 0/3] qemu: Call migrate-incoming with exit-on-error=false

See 3/3 for details. Jiri Denemark (3): qemu: Detect exit-on-error argument of migrate-incoming qemu: Replace qemuDomainCheckMonitor with qemuMigrationJobCheckStatus qemu: Call migrate-incoming with exit-on-error=false src/qemu/qemu_capabilities.c | 4 ++++ src/qemu/qemu_capabilities.h | 3 +++ src/qemu/qemu_domain.c | 18 ------------------ src/qemu/qemu_domain.h | 3 --- src/qemu/qemu_migration.c | 16 ++++++++++++---- src/qemu/qemu_monitor.c | 16 +++++----------- src/qemu/qemu_monitor.h | 4 ++-- src/qemu/qemu_monitor_json.c | 4 +++- src/qemu/qemu_monitor_json.h | 3 ++- .../caps_9.1.0_riscv64.xml | 1 + .../qemucapabilitiesdata/caps_9.1.0_s390x.xml | 1 + .../qemucapabilitiesdata/caps_9.1.0_x86_64.xml | 1 + .../qemucapabilitiesdata/caps_9.2.0_s390x.xml | 1 + .../qemucapabilitiesdata/caps_9.2.0_x86_64.xml | 1 + 14 files changed, 36 insertions(+), 40 deletions(-) -- 2.47.1

The exit-on-error argument (added in QEMU 9.1.0) can be used to tell QEMU not to exit when incoming migration fails so that the error can be retrieved via QMP. This patch adds a new capability bit indicating support for the new argument. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_capabilities.c | 4 ++++ src/qemu/qemu_capabilities.h | 3 +++ tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml | 1 + tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml | 1 + tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml | 1 + tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml | 1 + 7 files changed, 12 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index eda3e6a4df..bc765b91b2 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -722,6 +722,9 @@ VIR_ENUM_IMPL(virQEMUCaps, "virtio-ccw.loadparm", /* QEMU_CAPS_VIRTIO_CCW_DEVICE_LOADPARM */ "netdev-stream-reconnect-miliseconds", /* QEMU_CAPS_NETDEV_STREAM_RECONNECT_MILISECONDS */ "query-cpu-model-expansion.deprecated-props", /* QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION_DEPRECATED_PROPS */ + + /* 470 */ + "migrate-incoming.exit-on-error", /* QEMU_CAPS_MIGRATE_INCOMING_EXIT_ON_ERROR */ ); @@ -1596,6 +1599,7 @@ static struct virQEMUCapsStringFlags virQEMUCapsQMPSchemaQueries[] = { { "screendump/arg-type/format/^png", QEMU_CAPS_SCREENSHOT_FORMAT_PNG }, { "set-numa-node/arg-type/+hmat-lb", QEMU_CAPS_NUMA_HMAT }, { "query-cpu-model-expansion/ret-type/deprecated-props", QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION_DEPRECATED_PROPS }, + { "migrate-incoming/arg-type/exit-on-error", QEMU_CAPS_MIGRATE_INCOMING_EXIT_ON_ERROR }, }; typedef struct _virQEMUCapsObjectTypeProps virQEMUCapsObjectTypeProps; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 6bfe99fce4..398749a136 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -702,6 +702,9 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_NETDEV_STREAM_RECONNECT_MILISECONDS, /* 'reconnect-ms' option for netdev stream supported */ QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION_DEPRECATED_PROPS, /* query-cpu-model-expansion may report deprecated CPU properties */ + /* 470 */ + QEMU_CAPS_MIGRATE_INCOMING_EXIT_ON_ERROR, /* exit-on-error argument of migrate-incoming command */ + QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml b/tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml index 1e7b1e622b..77f4deca03 100644 --- a/tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml +++ b/tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml @@ -168,6 +168,7 @@ <flag name='netdev.user'/> <flag name='acpi-erst'/> <flag name='snapshot-internal-qmp'/> + <flag name='migrate-incoming.exit-on-error'/> <version>9001000</version> <microcodeVersion>0</microcodeVersion> <package>v9.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml b/tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml index b3265dcc18..a20b63051e 100644 --- a/tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml +++ b/tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml @@ -134,6 +134,7 @@ <flag name='netdev.user'/> <flag name='snapshot-internal-qmp'/> <flag name='query-cpu-model-expansion.deprecated-props'/> + <flag name='migrate-incoming.exit-on-error'/> <version>9001000</version> <microcodeVersion>39100246</microcodeVersion> <package>v9.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml index 06600f48fb..196bab7797 100644 --- a/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml @@ -208,6 +208,7 @@ <flag name='intel-iommu.dma-translation'/> <flag name='machine-i8042-opt'/> <flag name='snapshot-internal-qmp'/> + <flag name='migrate-incoming.exit-on-error'/> <version>9001000</version> <microcodeVersion>43100246</microcodeVersion> <package>v9.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml b/tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml index c3a9b62ec0..767a95bd3e 100644 --- a/tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml +++ b/tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml @@ -137,6 +137,7 @@ <flag name='virtio-ccw.loadparm'/> <flag name='netdev-stream-reconnect-miliseconds'/> <flag name='query-cpu-model-expansion.deprecated-props'/> + <flag name='migrate-incoming.exit-on-error'/> <version>9001050</version> <microcodeVersion>39100247</microcodeVersion> <package>v9.1.0-1348-g11b8920ed2</package> diff --git a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml index 982b7ad436..4eb395b6bc 100644 --- a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml @@ -210,6 +210,7 @@ <flag name='snapshot-internal-qmp'/> <flag name='chardev-reconnect-miliseconds'/> <flag name='netdev-stream-reconnect-miliseconds'/> + <flag name='migrate-incoming.exit-on-error'/> <version>9001090</version> <microcodeVersion>43100247</microcodeVersion> <package>v9.2.0-rc0-42-g3428a3894c</package> -- 2.47.1

The function is only used during incoming migration in the beginning of Finish phase to detect if QEMU already died but EOF handler haven't had a chance to do its job yet. It calls query-status QMP command, but ignores the result. By calling query-migrate instead we can achieve the same functionality if QEMU is dead and even get meaningful error from "error-desc" in case the incoming migration failed and QEMU is still running. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_domain.c | 18 ------------------ src/qemu/qemu_domain.h | 3 --- src/qemu/qemu_migration.c | 7 ++++--- src/qemu/qemu_monitor.c | 8 -------- src/qemu/qemu_monitor.h | 1 - 5 files changed, 4 insertions(+), 33 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 3366346624..f15ba58179 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -9007,24 +9007,6 @@ qemuDomainVcpuPersistOrder(virDomainDef *def) } -int -qemuDomainCheckMonitor(virDomainObj *vm, - virDomainAsyncJob asyncJob) -{ - qemuDomainObjPrivate *priv = vm->privateData; - int ret; - - if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0) - return -1; - - ret = qemuMonitorCheck(priv->mon); - - qemuDomainObjExitMonitor(vm); - - return ret; -} - - bool qemuDomainSupportsVideoVga(const virDomainVideoDef *video, virQEMUCaps *qemuCaps) diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index e810f79599..86e24ad54b 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -968,9 +968,6 @@ bool qemuDomainVcpuHotplugIsInOrder(virDomainDef *def) void qemuDomainVcpuPersistOrder(virDomainDef *def) ATTRIBUTE_NONNULL(1); -int qemuDomainCheckMonitor(virDomainObj *vm, - virDomainAsyncJob asyncJob); - bool qemuDomainSupportsVideoVga(const virDomainVideoDef *video, virQEMUCaps *qemuCaps); diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 26a92d8ee2..f9f40a2b03 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -6850,10 +6850,11 @@ qemuMigrationDstFinishActive(virQEMUDriver *driver, goto error; if (retcode != 0) { - /* Check for a possible error on the monitor in case Finish was called - * earlier than monitor EOF handler got a chance to process the error + /* Checking the migration status will read the migration error if + * set and QEMU is still alive. If the process died and EOF handler + * was not run yet, the appropriate monitor error will be set. */ - qemuDomainCheckMonitor(vm, VIR_ASYNC_JOB_MIGRATION_IN); + qemuMigrationJobCheckStatus(vm, VIR_ASYNC_JOB_MIGRATION_IN); goto error; } diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index df7e0d8997..c198ddb625 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -1430,14 +1430,6 @@ qemuMonitorStopCPUs(qemuMonitor *mon) } -int -qemuMonitorCheck(qemuMonitor *mon) -{ - bool running; - return qemuMonitorGetStatus(mon, &running, NULL); -} - - int qemuMonitorGetStatus(qemuMonitor *mon, bool *running, diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index d4d9b98ba7..ac3a7b6db3 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -558,7 +558,6 @@ typedef enum { VIR_ENUM_DECL(qemuMonitorVMStatus); int qemuMonitorVMStatusToPausedReason(const char *status); -int qemuMonitorCheck(qemuMonitor *mon); int qemuMonitorGetStatus(qemuMonitor *mon, bool *running, virDomainPausedReason *reason) -- 2.47.1

The exit-on-error=false argument of migrate-incoming tells the QEMU process to keep running when incoming migration fails, which helps us in two ways: 1. When migration enters Finish phase to cleanup the process, the domain might not even exist on the destination (because it has already been cleaned up by EOF monitor callback) and we would get rather unhelpful "operation failed: domain is no longer running" error message. 2. We can get the error that caused incoming migration to fail directly from QEMU via query-migrate QMP command. https://issues.redhat.com/browse/RHEL-7041 Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_migration.c | 9 ++++++++- src/qemu/qemu_monitor.c | 8 +++++--- src/qemu/qemu_monitor.h | 3 ++- src/qemu/qemu_monitor_json.c | 4 +++- src/qemu/qemu_monitor_json.h | 3 ++- 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index f9f40a2b03..50e350b0c4 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -2378,11 +2378,18 @@ qemuMigrationDstRun(virDomainObj *vm, const char *uri, virDomainAsyncJob asyncJob) { + virTristateBool exitOnError = VIR_TRISTATE_BOOL_ABSENT; qemuDomainObjPrivate *priv = vm->privateData; int rv; VIR_DEBUG("Setting up incoming migration with URI %s", uri); + /* Ask QEMU not to exit on failure during incoming migration (if supported) + * so that we can properly check and report error during Finish phase. + */ + if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_INCOMING_EXIT_ON_ERROR)) + exitOnError = VIR_TRISTATE_BOOL_NO; + if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0) return -1; @@ -2390,7 +2397,7 @@ qemuMigrationDstRun(virDomainObj *vm, if (rv < 0) goto exit_monitor; - rv = qemuMonitorMigrateIncoming(priv->mon, uri); + rv = qemuMonitorMigrateIncoming(priv->mon, uri, exitOnError); exit_monitor: qemuDomainObjExitMonitor(vm); diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index c198ddb625..ec2f166785 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3811,13 +3811,15 @@ qemuMonitorGetMemoryDeviceInfo(qemuMonitor *mon, int qemuMonitorMigrateIncoming(qemuMonitor *mon, - const char *uri) + const char *uri, + virTristateBool exitOnError) { - VIR_DEBUG("uri=%s", uri); + VIR_DEBUG("uri=%s, exitOnError=%s", + uri, virTristateBoolTypeToString(exitOnError)); QEMU_CHECK_MONITOR(mon); - return qemuMonitorJSONMigrateIncoming(mon, uri); + return qemuMonitorJSONMigrateIncoming(mon, uri, exitOnError); } diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index ac3a7b6db3..c74892c4dc 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1294,7 +1294,8 @@ int qemuMonitorGetMemoryDeviceInfo(qemuMonitor *mon, ATTRIBUTE_NONNULL(2); int qemuMonitorMigrateIncoming(qemuMonitor *mon, - const char *uri); + const char *uri, + virTristateBool exitOnError); int qemuMonitorMigrateStartPostCopy(qemuMonitor *mon); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 6500e01d3f..9f417d27c6 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -7269,13 +7269,15 @@ qemuMonitorJSONFindLinkPath(qemuMonitor *mon, int qemuMonitorJSONMigrateIncoming(qemuMonitor *mon, - const char *uri) + const char *uri, + virTristateBool exitOnError) { g_autoptr(virJSONValue) cmd = NULL; g_autoptr(virJSONValue) reply = NULL; if (!(cmd = qemuMonitorJSONMakeCommand("migrate-incoming", "s:uri", uri, + "T:exit-on-error", exitOnError, NULL))) return -1; diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 0214e9e9ff..2f5a021f56 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -607,7 +607,8 @@ qemuMonitorJSONFindLinkPath(qemuMonitor *mon, int qemuMonitorJSONMigrateIncoming(qemuMonitor *mon, - const char *uri) + const char *uri, + virTristateBool exitOnError) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); int -- 2.47.1

On 12/18/24 13:05, Jiri Denemark wrote:
See 3/3 for details.
Jiri Denemark (3): qemu: Detect exit-on-error argument of migrate-incoming qemu: Replace qemuDomainCheckMonitor with qemuMigrationJobCheckStatus qemu: Call migrate-incoming with exit-on-error=false
src/qemu/qemu_capabilities.c | 4 ++++ src/qemu/qemu_capabilities.h | 3 +++ src/qemu/qemu_domain.c | 18 ------------------ src/qemu/qemu_domain.h | 3 --- src/qemu/qemu_migration.c | 16 ++++++++++++---- src/qemu/qemu_monitor.c | 16 +++++----------- src/qemu/qemu_monitor.h | 4 ++-- src/qemu/qemu_monitor_json.c | 4 +++- src/qemu/qemu_monitor_json.h | 3 ++- .../caps_9.1.0_riscv64.xml | 1 + .../qemucapabilitiesdata/caps_9.1.0_s390x.xml | 1 + .../qemucapabilitiesdata/caps_9.1.0_x86_64.xml | 1 + .../qemucapabilitiesdata/caps_9.2.0_s390x.xml | 1 + .../qemucapabilitiesdata/caps_9.2.0_x86_64.xml | 1 + 14 files changed, 36 insertions(+), 40 deletions(-)
Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Michal
participants (2)
-
Jiri Denemark
-
Michal Prívozník