From fe7f49b39bbf512336d54238c68342a6350df659 Mon Sep 17 00:00:00 2001 From: Jiri Denemark Date: Fri, 29 Jul 2022 14:44:47 +0200 Subject: [PATCH] libvirt-8.5.0-4.el9 - qemu: Pass migration flags to qemuMigrationParamsApply (rhbz#2111070) - qemu_migration_params: Replace qemuMigrationParamTypes array (rhbz#2111070) - qemu_migration: Pass migParams to qemuMigrationSrcResume (rhbz#2111070) - qemu_migration: Apply max-postcopy-bandwidth on post-copy resume (rhbz#2111070) - qemu: Always assume support for QEMU_CAPS_MIGRATION_PARAM_XBZRLE_CACHE_SIZE (rhbz#2107892) - qemu_migration: Store original migration params in status XML (rhbz#2107892) - qemu_migration_params: Refactor qemuMigrationParamsApply (rhbz#2107892) - qemu_migration_params: Refactor qemuMigrationParamsReset (rhbz#2107892) - qemu_migration_params: Avoid deadlock in qemuMigrationParamsReset (rhbz#2107892) - qemu: Restore original memory locking limit on reconnect (rhbz#2107424) - qemu: Properly release job in qemuDomainSaveInternal (rhbz#1497907) - qemu: don't call qemuMigrationSrcIsAllowedHostdev() from qemuMigrationDstPrepareFresh() (rhbz#1497907) Resolves: rhbz#2107424, rhbz#2107892, rhbz#2111070 Related: rhbz#1497907 --- ...PS_MIGRATION_PARAM_XBZRLE_CACHE_SIZE.patch | 183 ++++++++++++++ ...on-flags-to-qemuMigrationParamsApply.patch | 148 +++++++++++ ...elease-job-in-qemuDomainSaveInternal.patch | 38 +++ ...al-memory-locking-limit-on-reconnect.patch | 85 +++++++ ...ev-from-qemuMigrationDstPrepareFresh.patch | 61 +++++ ...stcopy-bandwidth-on-post-copy-resume.patch | 229 ++++++++++++++++++ ...-migParams-to-qemuMigrationSrcResume.patch | 70 ++++++ ...ginal-migration-params-in-status-XML.patch | 51 ++++ ...deadlock-in-qemuMigrationParamsReset.patch | 62 +++++ ...ms-Refactor-qemuMigrationParamsApply.patch | 107 ++++++++ ...ms-Refactor-qemuMigrationParamsReset.patch | 63 +++++ ...eplace-qemuMigrationParamTypes-array.patch | 176 ++++++++++++++ libvirt.spec | 28 ++- 13 files changed, 1300 insertions(+), 1 deletion(-) create mode 100644 libvirt-qemu-Always-assume-support-for-QEMU_CAPS_MIGRATION_PARAM_XBZRLE_CACHE_SIZE.patch create mode 100644 libvirt-qemu-Pass-migration-flags-to-qemuMigrationParamsApply.patch create mode 100644 libvirt-qemu-Properly-release-job-in-qemuDomainSaveInternal.patch create mode 100644 libvirt-qemu-Restore-original-memory-locking-limit-on-reconnect.patch create mode 100644 libvirt-qemu-don-t-call-qemuMigrationSrcIsAllowedHostdev-from-qemuMigrationDstPrepareFresh.patch create mode 100644 libvirt-qemu_migration-Apply-max-postcopy-bandwidth-on-post-copy-resume.patch create mode 100644 libvirt-qemu_migration-Pass-migParams-to-qemuMigrationSrcResume.patch create mode 100644 libvirt-qemu_migration-Store-original-migration-params-in-status-XML.patch create mode 100644 libvirt-qemu_migration_params-Avoid-deadlock-in-qemuMigrationParamsReset.patch create mode 100644 libvirt-qemu_migration_params-Refactor-qemuMigrationParamsApply.patch create mode 100644 libvirt-qemu_migration_params-Refactor-qemuMigrationParamsReset.patch create mode 100644 libvirt-qemu_migration_params-Replace-qemuMigrationParamTypes-array.patch diff --git a/libvirt-qemu-Always-assume-support-for-QEMU_CAPS_MIGRATION_PARAM_XBZRLE_CACHE_SIZE.patch b/libvirt-qemu-Always-assume-support-for-QEMU_CAPS_MIGRATION_PARAM_XBZRLE_CACHE_SIZE.patch new file mode 100644 index 0000000..7ecdf33 --- /dev/null +++ b/libvirt-qemu-Always-assume-support-for-QEMU_CAPS_MIGRATION_PARAM_XBZRLE_CACHE_SIZE.patch @@ -0,0 +1,183 @@ +From b020ddee84458afd8de70d9f296b91fa2b6a95fd Mon Sep 17 00:00:00 2001 +Message-Id: +From: Peter Krempa +Date: Fri, 15 Jul 2022 14:16:54 +0200 +Subject: [PATCH] qemu: Always assume support for + QEMU_CAPS_MIGRATION_PARAM_XBZRLE_CACHE_SIZE + +The 'xbzrle-cache-size' parameter was added in qemu-2.11 thus all +supported qemu versions now use the new code path. + +Signed-off-by: Peter Krempa +Reviewed-by: Michal Privoznik +(cherry picked from commit 06e0ba3da71ec6c58024efe57d0f55d3d1352d60) + +This commit is not strictly needed for fixing the following BZ, but it +removes a code which will be never executed in RHEL 9 and backporting it +avoids conflicts with the actual bug fix. + +https://bugzilla.redhat.com/show_bug.cgi?id=2107892 + +Signed-off-by: Jiri Denemark +--- + src/qemu/qemu_driver.c | 56 +++++++++----------------------- + src/qemu/qemu_migration_params.c | 18 ---------- + 2 files changed, 16 insertions(+), 58 deletions(-) + +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index 17e4c23199..256e126ae1 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -13172,10 +13172,8 @@ qemuDomainMigrateGetCompressionCache(virDomainPtr dom, + { + virQEMUDriver *driver = dom->conn->privateData; + virDomainObj *vm; +- qemuDomainObjPrivate *priv; + g_autoptr(qemuMigrationParams) migParams = NULL; + int ret = -1; +- int rc; + + virCheckFlags(0, -1); + +@@ -13191,8 +13189,6 @@ qemuDomainMigrateGetCompressionCache(virDomainPtr dom, + if (virDomainObjCheckActive(vm) < 0) + goto endjob; + +- priv = vm->privateData; +- + if (!qemuMigrationCapsGet(vm, QEMU_MIGRATION_CAP_XBZRLE)) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("Compressed migration is not supported by " +@@ -13200,22 +13196,14 @@ qemuDomainMigrateGetCompressionCache(virDomainPtr dom, + goto endjob; + } + +- if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATION_PARAM_XBZRLE_CACHE_SIZE)) { +- if (qemuMigrationParamsFetch(driver, vm, VIR_ASYNC_JOB_NONE, +- &migParams) < 0) +- goto endjob; ++ if (qemuMigrationParamsFetch(driver, vm, VIR_ASYNC_JOB_NONE, ++ &migParams) < 0) ++ goto endjob; + +- if (qemuMigrationParamsGetULL(migParams, +- QEMU_MIGRATION_PARAM_XBZRLE_CACHE_SIZE, +- cacheSize) < 0) +- goto endjob; +- } else { +- qemuDomainObjEnterMonitor(driver, vm); +- rc = qemuMonitorGetMigrationCacheSize(priv->mon, cacheSize); +- qemuDomainObjExitMonitor(vm); +- if (rc < 0) +- goto endjob; +- } ++ if (qemuMigrationParamsGetULL(migParams, ++ QEMU_MIGRATION_PARAM_XBZRLE_CACHE_SIZE, ++ cacheSize) < 0) ++ goto endjob; + + ret = 0; + +@@ -13234,10 +13222,8 @@ qemuDomainMigrateSetCompressionCache(virDomainPtr dom, + { + virQEMUDriver *driver = dom->conn->privateData; + virDomainObj *vm; +- qemuDomainObjPrivate *priv; + g_autoptr(qemuMigrationParams) migParams = NULL; + int ret = -1; +- int rc; + + virCheckFlags(0, -1); + +@@ -13253,8 +13239,6 @@ qemuDomainMigrateSetCompressionCache(virDomainPtr dom, + if (virDomainObjCheckActive(vm) < 0) + goto endjob; + +- priv = vm->privateData; +- + if (!qemuMigrationCapsGet(vm, QEMU_MIGRATION_CAP_XBZRLE)) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("Compressed migration is not supported by " +@@ -13263,25 +13247,17 @@ qemuDomainMigrateSetCompressionCache(virDomainPtr dom, + } + + VIR_DEBUG("Setting compression cache to %llu B", cacheSize); +- if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATION_PARAM_XBZRLE_CACHE_SIZE)) { +- if (!(migParams = qemuMigrationParamsNew())) +- goto endjob; ++ if (!(migParams = qemuMigrationParamsNew())) ++ goto endjob; + +- if (qemuMigrationParamsSetULL(migParams, +- QEMU_MIGRATION_PARAM_XBZRLE_CACHE_SIZE, +- cacheSize) < 0) +- goto endjob; ++ if (qemuMigrationParamsSetULL(migParams, ++ QEMU_MIGRATION_PARAM_XBZRLE_CACHE_SIZE, ++ cacheSize) < 0) ++ goto endjob; + +- if (qemuMigrationParamsApply(driver, vm, VIR_ASYNC_JOB_NONE, +- migParams, 0) < 0) +- goto endjob; +- } else { +- qemuDomainObjEnterMonitor(driver, vm); +- rc = qemuMonitorSetMigrationCacheSize(priv->mon, cacheSize); +- qemuDomainObjExitMonitor(vm); +- if (rc < 0) +- goto endjob; +- } ++ if (qemuMigrationParamsApply(driver, vm, VIR_ASYNC_JOB_NONE, ++ migParams, 0) < 0) ++ goto endjob; + + ret = 0; + +diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c +index 6ea0bde13a..0bce358ac3 100644 +--- a/src/qemu/qemu_migration_params.c ++++ b/src/qemu/qemu_migration_params.c +@@ -886,10 +886,8 @@ qemuMigrationParamsApply(virQEMUDriver *driver, + unsigned long apiFlags) + { + qemuDomainObjPrivate *priv = vm->privateData; +- bool xbzrleCacheSize_old = false; + g_autoptr(virJSONValue) params = NULL; + g_autoptr(virJSONValue) caps = NULL; +- qemuMigrationParam xbzrle = QEMU_MIGRATION_PARAM_XBZRLE_CACHE_SIZE; + bool postcopyResume = !!(apiFlags & VIR_MIGRATE_POSTCOPY_RESUME); + int ret = -1; + +@@ -917,19 +915,6 @@ qemuMigrationParamsApply(virQEMUDriver *driver, + } + } + +- /* If QEMU is too old to support xbzrle-cache-size migration parameter, +- * we need to set it via migrate-set-cache-size and tell +- * qemuMonitorSetMigrationParams to ignore this parameter. +- */ +- if (migParams->params[xbzrle].set && +- !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATION_PARAM_XBZRLE_CACHE_SIZE)) { +- if (qemuMonitorSetMigrationCacheSize(priv->mon, +- migParams->params[xbzrle].value.ull) < 0) +- goto cleanup; +- xbzrleCacheSize_old = true; +- migParams->params[xbzrle].set = false; +- } +- + if (!(params = qemuMigrationParamsToJSON(migParams, postcopyResume))) + goto cleanup; + +@@ -942,9 +927,6 @@ qemuMigrationParamsApply(virQEMUDriver *driver, + cleanup: + qemuDomainObjExitMonitor(vm); + +- if (xbzrleCacheSize_old) +- migParams->params[xbzrle].set = true; +- + return ret; + } + +-- +2.35.1 + diff --git a/libvirt-qemu-Pass-migration-flags-to-qemuMigrationParamsApply.patch b/libvirt-qemu-Pass-migration-flags-to-qemuMigrationParamsApply.patch new file mode 100644 index 0000000..a94344e --- /dev/null +++ b/libvirt-qemu-Pass-migration-flags-to-qemuMigrationParamsApply.patch @@ -0,0 +1,148 @@ +From 4c906acec14efe3893491d749465ed7e285a825c Mon Sep 17 00:00:00 2001 +Message-Id: <4c906acec14efe3893491d749465ed7e285a825c@dist-git> +From: Jiri Denemark +Date: Wed, 29 Jun 2022 12:00:03 +0200 +Subject: [PATCH] qemu: Pass migration flags to qemuMigrationParamsApply + +The flags will later be used to determine which parameters should +actually be applied. + +Signed-off-by: Jiri Denemark +Reviewed-by: Michal Privoznik +(cherry picked from commit 0eae541257cd4f01c9d90db62056ad8d03c5af23) + +https://bugzilla.redhat.com/show_bug.cgi?id=2111070 + +Signed-off-by: Jiri Denemark +--- + src/qemu/qemu_driver.c | 6 +++--- + src/qemu/qemu_migration.c | 8 ++++---- + src/qemu/qemu_migration_params.c | 11 ++++++++--- + src/qemu/qemu_migration_params.h | 3 ++- + 4 files changed, 17 insertions(+), 11 deletions(-) + +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index 847c96639d..17e4c23199 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -13091,7 +13091,7 @@ qemuDomainMigrateSetMaxDowntime(virDomainPtr dom, + goto endjob; + + if (qemuMigrationParamsApply(driver, vm, VIR_ASYNC_JOB_NONE, +- migParams) < 0) ++ migParams, 0) < 0) + goto endjob; + } else { + qemuDomainObjEnterMonitor(driver, vm); +@@ -13273,7 +13273,7 @@ qemuDomainMigrateSetCompressionCache(virDomainPtr dom, + goto endjob; + + if (qemuMigrationParamsApply(driver, vm, VIR_ASYNC_JOB_NONE, +- migParams) < 0) ++ migParams, 0) < 0) + goto endjob; + } else { + qemuDomainObjEnterMonitor(driver, vm); +@@ -13360,7 +13360,7 @@ qemuDomainMigrateSetMaxSpeed(virDomainPtr dom, + goto endjob; + + if (qemuMigrationParamsApply(driver, vm, VIR_ASYNC_JOB_NONE, +- migParams) < 0) ++ migParams, 0) < 0) + goto endjob; + } else { + int rc; +diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c +index 76903d612b..8cbd73a809 100644 +--- a/src/qemu/qemu_migration.c ++++ b/src/qemu/qemu_migration.c +@@ -3259,7 +3259,7 @@ qemuMigrationDstPrepareActive(virQEMUDriver *driver, + } + + if (qemuMigrationParamsApply(driver, vm, VIR_ASYNC_JOB_MIGRATION_IN, +- migParams) < 0) ++ migParams, flags) < 0) + goto error; + + if (mig->nbd && +@@ -4847,7 +4847,7 @@ qemuMigrationSrcRun(virQEMUDriver *driver, + goto error; + + if (qemuMigrationParamsApply(driver, vm, VIR_ASYNC_JOB_MIGRATION_OUT, +- migParams) < 0) ++ migParams, flags) < 0) + goto error; + + if (flags & VIR_MIGRATE_ZEROCOPY) { +@@ -6941,7 +6941,7 @@ qemuMigrationSrcToFile(virQEMUDriver *driver, virDomainObj *vm, + QEMU_DOMAIN_MIG_BANDWIDTH_MAX * 1024 * 1024) < 0) + return -1; + +- if (qemuMigrationParamsApply(driver, vm, asyncJob, migParams) < 0) ++ if (qemuMigrationParamsApply(driver, vm, asyncJob, migParams, 0) < 0) + return -1; + + priv->migMaxBandwidth = QEMU_DOMAIN_MIG_BANDWIDTH_MAX; +@@ -7037,7 +7037,7 @@ qemuMigrationSrcToFile(virQEMUDriver *driver, virDomainObj *vm, + QEMU_MIGRATION_PARAM_MAX_BANDWIDTH, + saveMigBandwidth * 1024 * 1024) == 0) + ignore_value(qemuMigrationParamsApply(driver, vm, asyncJob, +- migParams)); ++ migParams, 0)); + } else { + if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) == 0) { + qemuMonitorSetMigrationSpeed(priv->mon, saveMigBandwidth); +diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c +index cc66ed8229..398c07efd0 100644 +--- a/src/qemu/qemu_migration_params.c ++++ b/src/qemu/qemu_migration_params.c +@@ -833,8 +833,10 @@ qemuMigrationCapsToJSON(virBitmap *caps, + * @vm: domain object + * @asyncJob: migration job + * @migParams: migration parameters to send to QEMU ++ * @apiFlags: migration flags, some of them may affect which parameters are applied + * +- * Send all parameters stored in @migParams to QEMU. ++ * Send parameters stored in @migParams to QEMU. If @apiFlags is non-zero, some ++ * parameters that do not make sense for the enabled flags will be ignored. + * + * Returns 0 on success, -1 on failure. + */ +@@ -842,7 +844,8 @@ int + qemuMigrationParamsApply(virQEMUDriver *driver, + virDomainObj *vm, + int asyncJob, +- qemuMigrationParams *migParams) ++ qemuMigrationParams *migParams, ++ unsigned long apiFlags G_GNUC_UNUSED) + { + qemuDomainObjPrivate *priv = vm->privateData; + bool xbzrleCacheSize_old = false; +@@ -1245,7 +1248,9 @@ qemuMigrationParamsReset(virQEMUDriver *driver, + if (!virDomainObjIsActive(vm) || !origParams) + goto cleanup; + +- if (qemuMigrationParamsApply(driver, vm, asyncJob, origParams) < 0) ++ /* Do not pass apiFlags to qemuMigrationParamsApply here to make sure all ++ * parameters and capabilities are reset. */ ++ if (qemuMigrationParamsApply(driver, vm, asyncJob, origParams, 0) < 0) + goto cleanup; + + qemuMigrationParamsResetTLS(driver, vm, asyncJob, origParams, apiFlags); +diff --git a/src/qemu/qemu_migration_params.h b/src/qemu/qemu_migration_params.h +index d1184acded..9e990e09bd 100644 +--- a/src/qemu/qemu_migration_params.h ++++ b/src/qemu/qemu_migration_params.h +@@ -98,7 +98,8 @@ int + qemuMigrationParamsApply(virQEMUDriver *driver, + virDomainObj *vm, + int asyncJob, +- qemuMigrationParams *migParams); ++ qemuMigrationParams *migParams, ++ unsigned long apiFlags); + + int + qemuMigrationParamsEnableTLS(virQEMUDriver *driver, +-- +2.35.1 + diff --git a/libvirt-qemu-Properly-release-job-in-qemuDomainSaveInternal.patch b/libvirt-qemu-Properly-release-job-in-qemuDomainSaveInternal.patch new file mode 100644 index 0000000..dd92c38 --- /dev/null +++ b/libvirt-qemu-Properly-release-job-in-qemuDomainSaveInternal.patch @@ -0,0 +1,38 @@ +From b35eb8dd4800be4dba22eb0a38da4d4d1c54521f Mon Sep 17 00:00:00 2001 +Message-Id: +From: Jiri Denemark +Date: Wed, 27 Jul 2022 15:40:12 +0200 +Subject: [PATCH] qemu: Properly release job in qemuDomainSaveInternal + +The function would fail to release the job in case +qemuMigrationSrcIsAllowed failed. + +Fixes v8.5.0-157-g69e0e33873 + +Signed-off-by: Jiri Denemark +Reviewed-by: Pavel Hrdina +(cherry picked from commit 9c3d398df11024ef6c00a50c98fcc0f1f66c16a1) + +https://bugzilla.redhat.com/show_bug.cgi?id=1497907 + +Signed-off-by: Jiri Denemark +--- + src/qemu/qemu_driver.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index 256e126ae1..ebd6365f52 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -2655,7 +2655,7 @@ qemuDomainSaveInternal(virQEMUDriver *driver, + goto cleanup; + + if (!qemuMigrationSrcIsAllowed(driver, vm, false, VIR_ASYNC_JOB_SAVE, 0)) +- goto cleanup; ++ goto endjob; + + if (!virDomainObjIsActive(vm)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +-- +2.35.1 + diff --git a/libvirt-qemu-Restore-original-memory-locking-limit-on-reconnect.patch b/libvirt-qemu-Restore-original-memory-locking-limit-on-reconnect.patch new file mode 100644 index 0000000..6b22dd7 --- /dev/null +++ b/libvirt-qemu-Restore-original-memory-locking-limit-on-reconnect.patch @@ -0,0 +1,85 @@ +From a1d825e5dcb8cbe0854fa852d25e5997a52d57cd Mon Sep 17 00:00:00 2001 +Message-Id: +From: Jiri Denemark +Date: Wed, 27 Jul 2022 14:33:23 +0200 +Subject: [PATCH] qemu: Restore original memory locking limit on reconnect + +Commit v8.4.0-287-gd4d3bb8130 tried to make sure the original +pre-migration memory locking limit is restored at the end of migration, +but it missed the case when libvirt daemon is restarted during +migration which needs to be aborted on reconnect. + +And if this was not enough, I forgot to actually save the status XML +after setting the field in priv (in the commit mentioned above and also +in v8.4.0-291-gd375993ab3). + +https://bugzilla.redhat.com/show_bug.cgi?id=2107424 + +Signed-off-by: Jiri Denemark +Reviewed-by: Michal Privoznik +(cherry picked from commit bb9badb9168ad0d40bca86b6463ef504624f096d) + +Conflicts: + src/qemu/qemu_migration.c + - commit v8.5.0-2-gf9dcc01a0f not backported + +Signed-off-by: Jiri Denemark +--- + src/qemu/qemu_migration.c | 13 +++++++++---- + src/qemu/qemu_process.c | 2 ++ + 2 files changed, 11 insertions(+), 4 deletions(-) + +diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c +index 9289df81eb..61fcaf4258 100644 +--- a/src/qemu/qemu_migration.c ++++ b/src/qemu/qemu_migration.c +@@ -4672,10 +4672,12 @@ qemuMigrationSrcStart(virDomainObj *vm, + switch (spec->destType) { + case MIGRATION_DEST_HOST: + if (STREQ(spec->dest.host.protocol, "rdma") && +- vm->def->mem.hard_limit > 0 && +- qemuDomainSetMaxMemLock(vm, vm->def->mem.hard_limit << 10, +- &priv->preMigrationMemlock) < 0) { +- return -1; ++ vm->def->mem.hard_limit > 0) { ++ if (qemuDomainSetMaxMemLock(vm, vm->def->mem.hard_limit << 10, ++ &priv->preMigrationMemlock) < 0) ++ return -1; ++ /* Store the original memory locking limit */ ++ qemuDomainSaveStatus(vm); + } + return qemuMonitorMigrateToHost(priv->mon, migrateFlags, + spec->dest.host.protocol, +@@ -4870,6 +4872,9 @@ qemuMigrationSrcRun(virQEMUDriver *driver, + + if (qemuDomainSetMaxMemLock(vm, limit << 10, &priv->preMigrationMemlock) < 0) + goto error; ++ ++ /* Store the original memory locking limit */ ++ qemuDomainSaveStatus(vm); + } + + if (storageMigration) { +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index 771a623ef7..1c28d4b102 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -3677,6 +3677,7 @@ qemuProcessRecoverMigration(virQEMUDriver *driver, + { + virDomainJobStatus migStatus = VIR_DOMAIN_JOB_STATUS_NONE; + qemuDomainJobPrivate *jobPriv = job->privateData; ++ qemuDomainObjPrivate *priv = vm->privateData; + virDomainState state; + int reason; + int rc; +@@ -3726,6 +3727,7 @@ qemuProcessRecoverMigration(virQEMUDriver *driver, + + qemuMigrationParamsReset(driver, vm, VIR_ASYNC_JOB_NONE, + jobPriv->migParams, job->apiFlags); ++ qemuDomainSetMaxMemLock(vm, 0, &priv->preMigrationMemlock); + + return 0; + } +-- +2.35.1 + diff --git a/libvirt-qemu-don-t-call-qemuMigrationSrcIsAllowedHostdev-from-qemuMigrationDstPrepareFresh.patch b/libvirt-qemu-don-t-call-qemuMigrationSrcIsAllowedHostdev-from-qemuMigrationDstPrepareFresh.patch new file mode 100644 index 0000000..537f227 --- /dev/null +++ b/libvirt-qemu-don-t-call-qemuMigrationSrcIsAllowedHostdev-from-qemuMigrationDstPrepareFresh.patch @@ -0,0 +1,61 @@ +From d51e6092ed7977daf662ed1def0f6cd5cc6ba33d Mon Sep 17 00:00:00 2001 +Message-Id: +From: Laine Stump +Date: Wed, 27 Jul 2022 12:14:10 -0400 +Subject: [PATCH] qemu: don't call qemuMigrationSrcIsAllowedHostdev() from + qemuMigrationDstPrepareFresh() + +This call to qemuMigrationSrcIsAllowedHostdev() (which does a +hardcoded fail of the migration if there is any PCI or mdev hostdev +device in the domain) while doing the destination side of migration +prep was found once the call to that same function was removed from +the source side migration prep (commit 25883cd5). + +According to jdenemar, for the V2 migration protocol, prep of the +destination is the first step, so this *was* the proper place to do +the check, but for V3 migration this is in a way redundant (since we +will have already done the check on the source side (updated by +25883cd5 to query QEMU rather than do a hardcoded fail)). + +Of course it's possible that the source could support migration of a +particular VFIO device, but the destination doesn't. But the current +check on the destination side is worthless even in that case, since it +is just *always* failing rather than querying QEMU; and QEMU can't be +queried at the point where the destination check is happening, since +it isn't yet running. + +Anyway QEMU should complain when it's started if it's going to fail, +so removing this check should just move the failure to happen a bit +later. So the best solution to this problem is to simply remove the +hardcoded check/fail from qemuMigrationDstPrepareFresh() and rely on +QEMU to fail if it needs to. + +Fixes: 25883cd5f0b188f2417f294b7d219a77b219f7c2 +Signed-off-by: Laine Stump +Reviewed-by: Jiri Denemark +(cherry picked from commit 640d185f01858b7a8db401235c929ac4798592d0) + +https://bugzilla.redhat.com/show_bug.cgi?id=1497907 + +Signed-off-by: Jiri Denemark +--- + src/qemu/qemu_migration.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c +index 61fcaf4258..e3ba4c3f78 100644 +--- a/src/qemu/qemu_migration.c ++++ b/src/qemu/qemu_migration.c +@@ -3382,9 +3382,6 @@ qemuMigrationDstPrepareFresh(virQEMUDriver *driver, + QEMU_MIGRATION_COOKIE_CAPS; + } + +- if (!qemuMigrationSrcIsAllowedHostdev(*def)) +- goto cleanup; +- + /* Let migration hook filter domain XML */ + if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) { + g_autofree char *xml = NULL; +-- +2.35.1 + diff --git a/libvirt-qemu_migration-Apply-max-postcopy-bandwidth-on-post-copy-resume.patch b/libvirt-qemu_migration-Apply-max-postcopy-bandwidth-on-post-copy-resume.patch new file mode 100644 index 0000000..bb7d0c6 --- /dev/null +++ b/libvirt-qemu_migration-Apply-max-postcopy-bandwidth-on-post-copy-resume.patch @@ -0,0 +1,229 @@ +From b8c791a3fc2767e6d899e3e0c590a93cb0ee7e03 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Jiri Denemark +Date: Thu, 30 Jun 2022 12:52:38 +0200 +Subject: [PATCH] qemu_migration: Apply max-postcopy-bandwidth on post-copy + resume + +When resuming post-copy migration users may want to limit the bandwidth +used by the migration and use a value that is different from the one +specified when the migration was originally started. + +Resolves: https://gitlab.com/libvirt/libvirt/-/issues/333 + +Signed-off-by: Jiri Denemark +Reviewed-by: Michal Privoznik +(cherry picked from commit 766abdc291ba606379a7d197bff477fef25fb508) + +https://bugzilla.redhat.com/show_bug.cgi?id=2111070 + +Signed-off-by: Jiri Denemark +--- + src/qemu/qemu_migration.c | 12 ++++++-- + src/qemu/qemu_migration_params.c | 45 ++++++++++++++++++---------- + src/qemu/qemu_migration_paramspriv.h | 3 +- + tests/qemumigparamstest.c | 2 +- + tests/qemumigrationcookiexmltest.c | 2 +- + 5 files changed, 42 insertions(+), 22 deletions(-) + +diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c +index 285a49c5ff..8a2f5b09a1 100644 +--- a/src/qemu/qemu_migration.c ++++ b/src/qemu/qemu_migration.c +@@ -5097,12 +5097,13 @@ qemuMigrationSrcRun(virQEMUDriver *driver, + + static int + qemuMigrationSrcResume(virDomainObj *vm, +- qemuMigrationParams *migParams G_GNUC_UNUSED, ++ qemuMigrationParams *migParams, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, +- qemuMigrationSpec *spec) ++ qemuMigrationSpec *spec, ++ unsigned long flags) + { + qemuDomainObjPrivate *priv = vm->privateData; + virQEMUDriver *driver = priv->driver; +@@ -5119,6 +5120,10 @@ qemuMigrationSrcResume(virDomainObj *vm, + if (!mig) + return -1; + ++ if (qemuMigrationParamsApply(driver, vm, VIR_ASYNC_JOB_MIGRATION_OUT, ++ migParams, flags) < 0) ++ return -1; ++ + if (qemuDomainObjEnterMonitorAsync(driver, vm, + VIR_ASYNC_JOB_MIGRATION_OUT) < 0) + return -1; +@@ -5200,6 +5205,7 @@ qemuMigrationSrcPerformNative(virQEMUDriver *driver, + + if (STREQ(uribits->scheme, "unix")) { + if ((flags & VIR_MIGRATE_TLS) && ++ !(flags & VIR_MIGRATE_POSTCOPY_RESUME) && + !qemuMigrationParamsTLSHostnameIsSet(migParams)) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("Explicit destination hostname is required " +@@ -5231,7 +5237,7 @@ qemuMigrationSrcPerformNative(virQEMUDriver *driver, + + if (flags & VIR_MIGRATE_POSTCOPY_RESUME) { + ret = qemuMigrationSrcResume(vm, migParams, cookiein, cookieinlen, +- cookieout, cookieoutlen, &spec); ++ cookieout, cookieoutlen, &spec, flags); + } else { + ret = qemuMigrationSrcRun(driver, vm, persist_xml, cookiein, cookieinlen, + cookieout, cookieoutlen, flags, resource, +diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c +index a68aed9aa4..6ea0bde13a 100644 +--- a/src/qemu/qemu_migration_params.c ++++ b/src/qemu/qemu_migration_params.c +@@ -141,6 +141,7 @@ struct _qemuMigrationParamsTPMapItem { + typedef struct _qemuMigrationParamInfoItem qemuMigrationParamInfoItem; + struct _qemuMigrationParamInfoItem { + qemuMigrationParamType type; ++ bool applyOnPostcopyResume; + }; + + /* Migration capabilities which should always be enabled as long as they +@@ -265,6 +266,7 @@ static const qemuMigrationParamInfoItem qemuMigrationParamInfo[] = { + }, + [QEMU_MIGRATION_PARAM_MAX_POSTCOPY_BANDWIDTH] = { + .type = QEMU_MIGRATION_PARAM_TYPE_ULL, ++ .applyOnPostcopyResume = true, + }, + [QEMU_MIGRATION_PARAM_MULTIFD_CHANNELS] = { + .type = QEMU_MIGRATION_PARAM_TYPE_INT, +@@ -782,7 +784,8 @@ qemuMigrationParamsFromJSON(virJSONValue *params) + + + virJSONValue * +-qemuMigrationParamsToJSON(qemuMigrationParams *migParams) ++qemuMigrationParamsToJSON(qemuMigrationParams *migParams, ++ bool postcopyResume) + { + g_autoptr(virJSONValue) params = virJSONValueNewObject(); + size_t i; +@@ -795,6 +798,9 @@ qemuMigrationParamsToJSON(qemuMigrationParams *migParams) + if (!pv->set) + continue; + ++ if (postcopyResume && !qemuMigrationParamInfo[i].applyOnPostcopyResume) ++ continue; ++ + switch (qemuMigrationParamInfo[i].type) { + case QEMU_MIGRATION_PARAM_TYPE_INT: + rc = virJSONValueObjectAppendNumberInt(params, name, pv->value.i); +@@ -868,6 +874,7 @@ qemuMigrationCapsToJSON(virBitmap *caps, + * + * Send parameters stored in @migParams to QEMU. If @apiFlags is non-zero, some + * parameters that do not make sense for the enabled flags will be ignored. ++ * VIR_MIGRATE_POSTCOPY_RESUME is the only flag checked currently. + * + * Returns 0 on success, -1 on failure. + */ +@@ -876,32 +883,38 @@ qemuMigrationParamsApply(virQEMUDriver *driver, + virDomainObj *vm, + int asyncJob, + qemuMigrationParams *migParams, +- unsigned long apiFlags G_GNUC_UNUSED) ++ unsigned long apiFlags) + { + qemuDomainObjPrivate *priv = vm->privateData; + bool xbzrleCacheSize_old = false; + g_autoptr(virJSONValue) params = NULL; + g_autoptr(virJSONValue) caps = NULL; + qemuMigrationParam xbzrle = QEMU_MIGRATION_PARAM_XBZRLE_CACHE_SIZE; ++ bool postcopyResume = !!(apiFlags & VIR_MIGRATE_POSTCOPY_RESUME); + int ret = -1; + + if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0) + return -1; + +- if (asyncJob == VIR_ASYNC_JOB_NONE) { +- if (!virBitmapIsAllClear(migParams->caps)) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("Migration capabilities can only be set by " +- "a migration job")); +- goto cleanup; +- } +- } else { +- if (!(caps = qemuMigrationCapsToJSON(priv->migrationCaps, migParams->caps))) +- goto cleanup; ++ /* Changing capabilities is only allowed before migration starts, we need ++ * to skip them when resuming post-copy migration. ++ */ ++ if (!postcopyResume) { ++ if (asyncJob == VIR_ASYNC_JOB_NONE) { ++ if (!virBitmapIsAllClear(migParams->caps)) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", ++ _("Migration capabilities can only be set by " ++ "a migration job")); ++ goto cleanup; ++ } ++ } else { ++ if (!(caps = qemuMigrationCapsToJSON(priv->migrationCaps, migParams->caps))) ++ goto cleanup; + +- if (virJSONValueArraySize(caps) > 0 && +- qemuMonitorSetMigrationCapabilities(priv->mon, &caps) < 0) +- goto cleanup; ++ if (virJSONValueArraySize(caps) > 0 && ++ qemuMonitorSetMigrationCapabilities(priv->mon, &caps) < 0) ++ goto cleanup; ++ } + } + + /* If QEMU is too old to support xbzrle-cache-size migration parameter, +@@ -917,7 +930,7 @@ qemuMigrationParamsApply(virQEMUDriver *driver, + migParams->params[xbzrle].set = false; + } + +- if (!(params = qemuMigrationParamsToJSON(migParams))) ++ if (!(params = qemuMigrationParamsToJSON(migParams, postcopyResume))) + goto cleanup; + + if (virJSONValueObjectKeysNumber(params) > 0 && +diff --git a/src/qemu/qemu_migration_paramspriv.h b/src/qemu/qemu_migration_paramspriv.h +index f7e0f51fbd..34d51231ff 100644 +--- a/src/qemu/qemu_migration_paramspriv.h ++++ b/src/qemu/qemu_migration_paramspriv.h +@@ -26,7 +26,8 @@ + #pragma once + + virJSONValue * +-qemuMigrationParamsToJSON(qemuMigrationParams *migParams); ++qemuMigrationParamsToJSON(qemuMigrationParams *migParams, ++ bool postcopyResume); + + qemuMigrationParams * + qemuMigrationParamsFromJSON(virJSONValue *params); +diff --git a/tests/qemumigparamstest.c b/tests/qemumigparamstest.c +index bcdee5f32b..5d45a9dd58 100644 +--- a/tests/qemumigparamstest.c ++++ b/tests/qemumigparamstest.c +@@ -155,7 +155,7 @@ qemuMigParamsTestJSON(const void *opaque) + if (!(migParams = qemuMigrationParamsFromJSON(paramsIn))) + return -1; + +- if (!(paramsOut = qemuMigrationParamsToJSON(migParams)) || ++ if (!(paramsOut = qemuMigrationParamsToJSON(migParams, false)) || + !(actualJSON = virJSONValueToString(paramsOut, true))) + return -1; + +diff --git a/tests/qemumigrationcookiexmltest.c b/tests/qemumigrationcookiexmltest.c +index 316bfedd15..9731348b53 100644 +--- a/tests/qemumigrationcookiexmltest.c ++++ b/tests/qemumigrationcookiexmltest.c +@@ -333,7 +333,7 @@ testQemuMigrationCookieBlockDirtyBitmaps(const void *opaque) + + qemuMigrationParamsSetBlockDirtyBitmapMapping(migParams, &migParamsBitmaps); + +- if (!(paramsOut = qemuMigrationParamsToJSON(migParams)) || ++ if (!(paramsOut = qemuMigrationParamsToJSON(migParams, false)) || + !(actualJSON = virJSONValueToString(paramsOut, true))) + return -1; + +-- +2.35.1 + diff --git a/libvirt-qemu_migration-Pass-migParams-to-qemuMigrationSrcResume.patch b/libvirt-qemu_migration-Pass-migParams-to-qemuMigrationSrcResume.patch new file mode 100644 index 0000000..a61b5e9 --- /dev/null +++ b/libvirt-qemu_migration-Pass-migParams-to-qemuMigrationSrcResume.patch @@ -0,0 +1,70 @@ +From d24586ede83472f850d1a0c520d482ac5f908696 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Jiri Denemark +Date: Thu, 30 Jun 2022 12:51:55 +0200 +Subject: [PATCH] qemu_migration: Pass migParams to qemuMigrationSrcResume + +So the we can apply selected migration parameters even when resuming +post-copy migration. + +Signed-off-by: Jiri Denemark +Reviewed-by: Michal Privoznik +(cherry picked from commit 8c335b5530194dbcef719a4d88c89b8723b831a5) + +https://bugzilla.redhat.com/show_bug.cgi?id=2111070 + +Signed-off-by: Jiri Denemark +--- + src/qemu/qemu_migration.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c +index 8cbd73a809..285a49c5ff 100644 +--- a/src/qemu/qemu_migration.c ++++ b/src/qemu/qemu_migration.c +@@ -5097,6 +5097,7 @@ qemuMigrationSrcRun(virQEMUDriver *driver, + + static int + qemuMigrationSrcResume(virDomainObj *vm, ++ qemuMigrationParams *migParams G_GNUC_UNUSED, + const char *cookiein, + int cookieinlen, + char **cookieout, +@@ -5229,7 +5230,7 @@ qemuMigrationSrcPerformNative(virQEMUDriver *driver, + spec.fwdType = MIGRATION_FWD_DIRECT; + + if (flags & VIR_MIGRATE_POSTCOPY_RESUME) { +- ret = qemuMigrationSrcResume(vm, cookiein, cookieinlen, ++ ret = qemuMigrationSrcResume(vm, migParams, cookiein, cookieinlen, + cookieout, cookieoutlen, &spec); + } else { + ret = qemuMigrationSrcRun(driver, vm, persist_xml, cookiein, cookieinlen, +@@ -6124,6 +6125,7 @@ qemuMigrationSrcPerformResume(virQEMUDriver *driver, + virConnectPtr conn, + virDomainObj *vm, + const char *uri, ++ qemuMigrationParams *migParams, + const char *cookiein, + int cookieinlen, + char **cookieout, +@@ -6148,7 +6150,7 @@ qemuMigrationSrcPerformResume(virQEMUDriver *driver, + ret = qemuMigrationSrcPerformNative(driver, vm, NULL, uri, + cookiein, cookieinlen, + cookieout, cookieoutlen, flags, +- 0, NULL, NULL, 0, NULL, NULL, NULL); ++ 0, NULL, NULL, 0, NULL, migParams, NULL); + + if (virCloseCallbacksSet(driver->closeCallbacks, vm, conn, + qemuMigrationAnyConnectionClosed) < 0) +@@ -6188,7 +6190,7 @@ qemuMigrationSrcPerformPhase(virQEMUDriver *driver, + int ret = -1; + + if (flags & VIR_MIGRATE_POSTCOPY_RESUME) { +- return qemuMigrationSrcPerformResume(driver, conn, vm, uri, ++ return qemuMigrationSrcPerformResume(driver, conn, vm, uri, migParams, + cookiein, cookieinlen, + cookieout, cookieoutlen, flags); + } +-- +2.35.1 + diff --git a/libvirt-qemu_migration-Store-original-migration-params-in-status-XML.patch b/libvirt-qemu_migration-Store-original-migration-params-in-status-XML.patch new file mode 100644 index 0000000..bd47311 --- /dev/null +++ b/libvirt-qemu_migration-Store-original-migration-params-in-status-XML.patch @@ -0,0 +1,51 @@ +From c50cae68f0d083ad0c5ffcf85908cc62eeaa866d Mon Sep 17 00:00:00 2001 +Message-Id: +From: Jiri Denemark +Date: Tue, 19 Jul 2022 13:48:44 +0200 +Subject: [PATCH] qemu_migration: Store original migration params in status XML + +We keep original values of migration parameters so that we can restore +them at the end of migration to make sure later migration does not use +some random values. However, this does not really work when libvirt +daemon is restarted on the source host because we failed to explicitly +save the status XML after getting the migration parameters from QEMU. +Actually it might work if the status XML is written later for some other +reason such as domain state change, but that's not how it should work. + +https://bugzilla.redhat.com/show_bug.cgi?id=2107892 + +Signed-off-by: Jiri Denemark +Reviewed-by: Michal Privoznik +(cherry picked from commit c7238941357f0d2e94524cf8c5ad7d9c82dcf2f9) +Signed-off-by: Jiri Denemark +--- + src/qemu/qemu_migration.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c +index 8a2f5b09a1..9289df81eb 100644 +--- a/src/qemu/qemu_migration.c ++++ b/src/qemu/qemu_migration.c +@@ -3245,6 +3245,9 @@ qemuMigrationDstPrepareActive(virQEMUDriver *driver, + migParams, mig->caps->automatic) < 0) + goto error; + ++ /* Save original migration parameters */ ++ qemuDomainSaveStatus(vm); ++ + /* Migrations using TLS need to add the "tls-creds-x509" object and + * set the migration TLS parameters */ + if (flags & VIR_MIGRATE_TLS) { +@@ -4822,6 +4825,9 @@ qemuMigrationSrcRun(virQEMUDriver *driver, + migParams, mig->caps->automatic) < 0) + goto error; + ++ /* Save original migration parameters */ ++ qemuDomainSaveStatus(vm); ++ + if (flags & VIR_MIGRATE_TLS) { + const char *hostname = NULL; + +-- +2.35.1 + diff --git a/libvirt-qemu_migration_params-Avoid-deadlock-in-qemuMigrationParamsReset.patch b/libvirt-qemu_migration_params-Avoid-deadlock-in-qemuMigrationParamsReset.patch new file mode 100644 index 0000000..53bf233 --- /dev/null +++ b/libvirt-qemu_migration_params-Avoid-deadlock-in-qemuMigrationParamsReset.patch @@ -0,0 +1,62 @@ +From 0022c9aef2ecf60e9091e6df57e56065b14b67c5 Mon Sep 17 00:00:00 2001 +Message-Id: <0022c9aef2ecf60e9091e6df57e56065b14b67c5@dist-git> +From: Jiri Denemark +Date: Thu, 28 Jul 2022 15:35:45 +0200 +Subject: [PATCH] qemu_migration_params: Avoid deadlock in + qemuMigrationParamsReset + +In my recent comnmit v8.5.0-188-gc47f1abb81 I accidentally moved +qemuMigrationParamsResetTLS after qemuDomainObjEnterMonitorAsync not +noticing qemuMigrationParamsResetTLS will try to enter the monitor +again. The second call will time out and return with a domain object +locked. But we're still in monitor section and the object should be +unlocked which means qemuDomainObjExitMonitor will deadlock trying to +lock it again. + +Fixes: c47f1abb81194461377a0c608a7ecd87f9ce9146 +Signed-off-by: Jiri Denemark +Reviewed-by: Michal Privoznik +(cherry picked from commit 8cb19a9b9a56ab6ebefc1f913c545e0bb86d4364) + +https://bugzilla.redhat.com/show_bug.cgi?id=2107892 + +Signed-off-by: Jiri Denemark +--- + src/qemu/qemu_migration_params.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c +index 4a824ff5e1..4766d16e64 100644 +--- a/src/qemu/qemu_migration_params.c ++++ b/src/qemu/qemu_migration_params.c +@@ -1291,6 +1291,7 @@ qemuMigrationParamsReset(virQEMUDriver *driver, + { + virErrorPtr err; + g_autoptr(virBitmap) clearCaps = NULL; ++ int rc; + + virErrorPreserveLast(&err); + +@@ -1305,11 +1306,16 @@ qemuMigrationParamsReset(virQEMUDriver *driver, + + clearCaps = virBitmapNew(0); + +- if (qemuMigrationParamsApplyCaps(vm, clearCaps) == 0 && +- qemuMigrationParamsApplyValues(vm, origParams, false) == 0) +- qemuMigrationParamsResetTLS(driver, vm, asyncJob, origParams, apiFlags); ++ rc = 0; ++ if (qemuMigrationParamsApplyCaps(vm, clearCaps) < 0 || ++ qemuMigrationParamsApplyValues(vm, origParams, false) < 0) ++ rc = -1; + + qemuDomainObjExitMonitor(vm); ++ if (rc < 0) ++ goto cleanup; ++ ++ qemuMigrationParamsResetTLS(driver, vm, asyncJob, origParams, apiFlags); + + cleanup: + virErrorRestore(&err); +-- +2.35.1 + diff --git a/libvirt-qemu_migration_params-Refactor-qemuMigrationParamsApply.patch b/libvirt-qemu_migration_params-Refactor-qemuMigrationParamsApply.patch new file mode 100644 index 0000000..c27146a --- /dev/null +++ b/libvirt-qemu_migration_params-Refactor-qemuMigrationParamsApply.patch @@ -0,0 +1,107 @@ +From 852927ea725deae6d4ef8a87383a78d9b0b1cd83 Mon Sep 17 00:00:00 2001 +Message-Id: <852927ea725deae6d4ef8a87383a78d9b0b1cd83@dist-git> +From: Jiri Denemark +Date: Thu, 21 Jul 2022 15:59:51 +0200 +Subject: [PATCH] qemu_migration_params: Refactor qemuMigrationParamsApply + +qemuMigrationParamsApply restricts when capabilities can be set, but +this is not useful in all cases. Let's create new helpers for setting +migration capabilities and parameters which can be reused in more places +without the restriction. + +https://bugzilla.redhat.com/show_bug.cgi?id=2107892 + +Signed-off-by: Jiri Denemark +Reviewed-by: Michal Privoznik +(cherry picked from commit c0824fd03802085db698c10fe62c98cc95a57941) +Signed-off-by: Jiri Denemark +--- + src/qemu/qemu_migration_params.c | 55 +++++++++++++++++++++++--------- + 1 file changed, 40 insertions(+), 15 deletions(-) + +diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c +index 0bce358ac3..7b9e5453f6 100644 +--- a/src/qemu/qemu_migration_params.c ++++ b/src/qemu/qemu_migration_params.c +@@ -864,6 +864,43 @@ qemuMigrationCapsToJSON(virBitmap *caps, + } + + ++static int ++qemuMigrationParamsApplyCaps(virDomainObj *vm, ++ virBitmap *states) ++{ ++ qemuDomainObjPrivate *priv = vm->privateData; ++ g_autoptr(virJSONValue) json = NULL; ++ ++ if (!(json = qemuMigrationCapsToJSON(priv->migrationCaps, states))) ++ return -1; ++ ++ if (virJSONValueArraySize(json) > 0 && ++ qemuMonitorSetMigrationCapabilities(priv->mon, &json) < 0) ++ return -1; ++ ++ return 0; ++} ++ ++ ++static int ++qemuMigrationParamsApplyValues(virDomainObj *vm, ++ qemuMigrationParams *params, ++ bool postcopyResume) ++{ ++ qemuDomainObjPrivate *priv = vm->privateData; ++ g_autoptr(virJSONValue) json = NULL; ++ ++ if (!(json = qemuMigrationParamsToJSON(params, postcopyResume))) ++ return -1; ++ ++ if (virJSONValueObjectKeysNumber(json) > 0 && ++ qemuMonitorSetMigrationParams(priv->mon, &json) < 0) ++ return -1; ++ ++ return 0; ++} ++ ++ + /** + * qemuMigrationParamsApply + * @driver: qemu driver +@@ -885,9 +922,6 @@ qemuMigrationParamsApply(virQEMUDriver *driver, + qemuMigrationParams *migParams, + unsigned long apiFlags) + { +- qemuDomainObjPrivate *priv = vm->privateData; +- g_autoptr(virJSONValue) params = NULL; +- g_autoptr(virJSONValue) caps = NULL; + bool postcopyResume = !!(apiFlags & VIR_MIGRATE_POSTCOPY_RESUME); + int ret = -1; + +@@ -905,21 +939,12 @@ qemuMigrationParamsApply(virQEMUDriver *driver, + "a migration job")); + goto cleanup; + } +- } else { +- if (!(caps = qemuMigrationCapsToJSON(priv->migrationCaps, migParams->caps))) +- goto cleanup; +- +- if (virJSONValueArraySize(caps) > 0 && +- qemuMonitorSetMigrationCapabilities(priv->mon, &caps) < 0) +- goto cleanup; ++ } else if (qemuMigrationParamsApplyCaps(vm, migParams->caps) < 0) { ++ goto cleanup; + } + } + +- if (!(params = qemuMigrationParamsToJSON(migParams, postcopyResume))) +- goto cleanup; +- +- if (virJSONValueObjectKeysNumber(params) > 0 && +- qemuMonitorSetMigrationParams(priv->mon, ¶ms) < 0) ++ if (qemuMigrationParamsApplyValues(vm, migParams, postcopyResume) < 0) + goto cleanup; + + ret = 0; +-- +2.35.1 + diff --git a/libvirt-qemu_migration_params-Refactor-qemuMigrationParamsReset.patch b/libvirt-qemu_migration_params-Refactor-qemuMigrationParamsReset.patch new file mode 100644 index 0000000..638447f --- /dev/null +++ b/libvirt-qemu_migration_params-Refactor-qemuMigrationParamsReset.patch @@ -0,0 +1,63 @@ +From 2a05454cd2d6ba283c128158f44d84d65832ebf7 Mon Sep 17 00:00:00 2001 +Message-Id: <2a05454cd2d6ba283c128158f44d84d65832ebf7@dist-git> +From: Jiri Denemark +Date: Thu, 21 Jul 2022 16:49:09 +0200 +Subject: [PATCH] qemu_migration_params: Refactor qemuMigrationParamsReset + +Because qemuMigrationParamsReset used to call qemuMigrationParamsApply +for resetting migration capabilities and parameters, it did not work +well since commit v5.1.0-83-ga1dec315c9 which only allowed capabilities +to be set from an async job. However, when reconnecting to running +domains after daemon restart we do not have an async job. Thus the +capabilities were not properly reset in case the daemon was restarted +during an ongoing migration. We need to avoid calling +qemuMigrationParamsApply to make sure both parameters and capabilities +can be reset by a normal job. + +https://bugzilla.redhat.com/show_bug.cgi?id=2107892 + +Signed-off-by: Jiri Denemark +Reviewed-by: Michal Privoznik +(cherry picked from commit c47f1abb81194461377a0c608a7ecd87f9ce9146) +Signed-off-by: Jiri Denemark +--- + src/qemu/qemu_migration_params.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c +index 7b9e5453f6..4a824ff5e1 100644 +--- a/src/qemu/qemu_migration_params.c ++++ b/src/qemu/qemu_migration_params.c +@@ -1290,6 +1290,7 @@ qemuMigrationParamsReset(virQEMUDriver *driver, + unsigned long apiFlags) + { + virErrorPtr err; ++ g_autoptr(virBitmap) clearCaps = NULL; + + virErrorPreserveLast(&err); + +@@ -1299,13 +1300,16 @@ qemuMigrationParamsReset(virQEMUDriver *driver, + if (!virDomainObjIsActive(vm) || !origParams) + goto cleanup; + +- /* Do not pass apiFlags to qemuMigrationParamsApply here to make sure all +- * parameters and capabilities are reset. */ +- if (qemuMigrationParamsApply(driver, vm, asyncJob, origParams, 0) < 0) ++ if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0) + goto cleanup; + +- qemuMigrationParamsResetTLS(driver, vm, asyncJob, origParams, apiFlags); +- /* We don't reset 'block-bitmap-mapping' as it can't be unset */ ++ clearCaps = virBitmapNew(0); ++ ++ if (qemuMigrationParamsApplyCaps(vm, clearCaps) == 0 && ++ qemuMigrationParamsApplyValues(vm, origParams, false) == 0) ++ qemuMigrationParamsResetTLS(driver, vm, asyncJob, origParams, apiFlags); ++ ++ qemuDomainObjExitMonitor(vm); + + cleanup: + virErrorRestore(&err); +-- +2.35.1 + diff --git a/libvirt-qemu_migration_params-Replace-qemuMigrationParamTypes-array.patch b/libvirt-qemu_migration_params-Replace-qemuMigrationParamTypes-array.patch new file mode 100644 index 0000000..a620ace --- /dev/null +++ b/libvirt-qemu_migration_params-Replace-qemuMigrationParamTypes-array.patch @@ -0,0 +1,176 @@ +From aa4b6b4877d60218c24d4ae713786f5ee37ac6dc Mon Sep 17 00:00:00 2001 +Message-Id: +From: Jiri Denemark +Date: Wed, 29 Jun 2022 15:12:20 +0200 +Subject: [PATCH] qemu_migration_params: Replace qemuMigrationParamTypes array + +We will need to annotate individual parameters a bit more than just +noting their type. Let's introduce qemuMigrationParamInfo replacing +simple qemuMigrationParamTypes with an array of structs. + +Signed-off-by: Jiri Denemark +Reviewed-by: Michal Privoznik +(cherry picked from commit 184749691f27f30a39f6f6c77828ffb951af0255) + +https://bugzilla.redhat.com/show_bug.cgi?id=2111070 + +Signed-off-by: Jiri Denemark +--- + src/qemu/qemu_migration_params.c | 77 ++++++++++++++++++++++---------- + 1 file changed, 54 insertions(+), 23 deletions(-) + +diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c +index 398c07efd0..a68aed9aa4 100644 +--- a/src/qemu/qemu_migration_params.c ++++ b/src/qemu/qemu_migration_params.c +@@ -138,6 +138,11 @@ struct _qemuMigrationParamsTPMapItem { + int party; /* bit-wise OR of qemuMigrationParty */ + }; + ++typedef struct _qemuMigrationParamInfoItem qemuMigrationParamInfoItem; ++struct _qemuMigrationParamInfoItem { ++ qemuMigrationParamType type; ++}; ++ + /* Migration capabilities which should always be enabled as long as they + * are supported by QEMU. If the capability is supposed to be enabled on both + * sides of migration, it won't be enabled unless both sides support it. +@@ -224,22 +229,48 @@ static const qemuMigrationParamsTPMapItem qemuMigrationParamsTPMap[] = { + .party = QEMU_MIGRATION_SOURCE}, + }; + +-static const qemuMigrationParamType qemuMigrationParamTypes[] = { +- [QEMU_MIGRATION_PARAM_COMPRESS_LEVEL] = QEMU_MIGRATION_PARAM_TYPE_INT, +- [QEMU_MIGRATION_PARAM_COMPRESS_THREADS] = QEMU_MIGRATION_PARAM_TYPE_INT, +- [QEMU_MIGRATION_PARAM_DECOMPRESS_THREADS] = QEMU_MIGRATION_PARAM_TYPE_INT, +- [QEMU_MIGRATION_PARAM_THROTTLE_INITIAL] = QEMU_MIGRATION_PARAM_TYPE_INT, +- [QEMU_MIGRATION_PARAM_THROTTLE_INCREMENT] = QEMU_MIGRATION_PARAM_TYPE_INT, +- [QEMU_MIGRATION_PARAM_TLS_CREDS] = QEMU_MIGRATION_PARAM_TYPE_STRING, +- [QEMU_MIGRATION_PARAM_TLS_HOSTNAME] = QEMU_MIGRATION_PARAM_TYPE_STRING, +- [QEMU_MIGRATION_PARAM_MAX_BANDWIDTH] = QEMU_MIGRATION_PARAM_TYPE_ULL, +- [QEMU_MIGRATION_PARAM_DOWNTIME_LIMIT] = QEMU_MIGRATION_PARAM_TYPE_ULL, +- [QEMU_MIGRATION_PARAM_BLOCK_INCREMENTAL] = QEMU_MIGRATION_PARAM_TYPE_BOOL, +- [QEMU_MIGRATION_PARAM_XBZRLE_CACHE_SIZE] = QEMU_MIGRATION_PARAM_TYPE_ULL, +- [QEMU_MIGRATION_PARAM_MAX_POSTCOPY_BANDWIDTH] = QEMU_MIGRATION_PARAM_TYPE_ULL, +- [QEMU_MIGRATION_PARAM_MULTIFD_CHANNELS] = QEMU_MIGRATION_PARAM_TYPE_INT, ++static const qemuMigrationParamInfoItem qemuMigrationParamInfo[] = { ++ [QEMU_MIGRATION_PARAM_COMPRESS_LEVEL] = { ++ .type = QEMU_MIGRATION_PARAM_TYPE_INT, ++ }, ++ [QEMU_MIGRATION_PARAM_COMPRESS_THREADS] = { ++ .type = QEMU_MIGRATION_PARAM_TYPE_INT, ++ }, ++ [QEMU_MIGRATION_PARAM_DECOMPRESS_THREADS] = { ++ .type = QEMU_MIGRATION_PARAM_TYPE_INT, ++ }, ++ [QEMU_MIGRATION_PARAM_THROTTLE_INITIAL] = { ++ .type = QEMU_MIGRATION_PARAM_TYPE_INT, ++ }, ++ [QEMU_MIGRATION_PARAM_THROTTLE_INCREMENT] = { ++ .type = QEMU_MIGRATION_PARAM_TYPE_INT, ++ }, ++ [QEMU_MIGRATION_PARAM_TLS_CREDS] = { ++ .type = QEMU_MIGRATION_PARAM_TYPE_STRING, ++ }, ++ [QEMU_MIGRATION_PARAM_TLS_HOSTNAME] = { ++ .type = QEMU_MIGRATION_PARAM_TYPE_STRING, ++ }, ++ [QEMU_MIGRATION_PARAM_MAX_BANDWIDTH] = { ++ .type = QEMU_MIGRATION_PARAM_TYPE_ULL, ++ }, ++ [QEMU_MIGRATION_PARAM_DOWNTIME_LIMIT] = { ++ .type = QEMU_MIGRATION_PARAM_TYPE_ULL, ++ }, ++ [QEMU_MIGRATION_PARAM_BLOCK_INCREMENTAL] = { ++ .type = QEMU_MIGRATION_PARAM_TYPE_BOOL, ++ }, ++ [QEMU_MIGRATION_PARAM_XBZRLE_CACHE_SIZE] = { ++ .type = QEMU_MIGRATION_PARAM_TYPE_ULL, ++ }, ++ [QEMU_MIGRATION_PARAM_MAX_POSTCOPY_BANDWIDTH] = { ++ .type = QEMU_MIGRATION_PARAM_TYPE_ULL, ++ }, ++ [QEMU_MIGRATION_PARAM_MULTIFD_CHANNELS] = { ++ .type = QEMU_MIGRATION_PARAM_TYPE_INT, ++ }, + }; +-G_STATIC_ASSERT(G_N_ELEMENTS(qemuMigrationParamTypes) == QEMU_MIGRATION_PARAM_LAST); ++G_STATIC_ASSERT(G_N_ELEMENTS(qemuMigrationParamInfo) == QEMU_MIGRATION_PARAM_LAST); + + + virBitmap * +@@ -281,7 +312,7 @@ qemuMigrationParamsFree(qemuMigrationParams *migParams) + return; + + for (i = 0; i < QEMU_MIGRATION_PARAM_LAST; i++) { +- if (qemuMigrationParamTypes[i] == QEMU_MIGRATION_PARAM_TYPE_STRING) ++ if (qemuMigrationParamInfo[i].type == QEMU_MIGRATION_PARAM_TYPE_STRING) + g_free(migParams->params[i].value.s); + } + +@@ -295,7 +326,7 @@ static int + qemuMigrationParamsCheckType(qemuMigrationParam param, + qemuMigrationParamType type) + { +- if (qemuMigrationParamTypes[param] != type) { ++ if (qemuMigrationParamInfo[param].type != type) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Type mismatch for '%s' migration parameter"), + qemuMigrationParamTypeToString(param)); +@@ -595,7 +626,7 @@ qemuMigrationParamsFromFlags(virTypedParameterPtr params, + VIR_DEBUG("Setting migration parameter '%s' from '%s'", + qemuMigrationParamTypeToString(item->param), item->typedParam); + +- switch (qemuMigrationParamTypes[item->param]) { ++ switch (qemuMigrationParamInfo[item->param].type) { + case QEMU_MIGRATION_PARAM_TYPE_INT: + if (qemuMigrationParamsGetTPInt(migParams, item->param, params, + nparams, item->typedParam, +@@ -671,7 +702,7 @@ qemuMigrationParamsDump(qemuMigrationParams *migParams, + if (!(item->party & QEMU_MIGRATION_DESTINATION)) + continue; + +- switch (qemuMigrationParamTypes[item->param]) { ++ switch (qemuMigrationParamInfo[item->param].type) { + case QEMU_MIGRATION_PARAM_TYPE_INT: + if (qemuMigrationParamsSetTPInt(migParams, item->param, + params, nparams, maxparams, +@@ -721,7 +752,7 @@ qemuMigrationParamsFromJSON(virJSONValue *params) + name = qemuMigrationParamTypeToString(i); + pv = &migParams->params[i]; + +- switch (qemuMigrationParamTypes[i]) { ++ switch (qemuMigrationParamInfo[i].type) { + case QEMU_MIGRATION_PARAM_TYPE_INT: + if (virJSONValueObjectGetNumberInt(params, name, &pv->value.i) == 0) + pv->set = true; +@@ -764,7 +795,7 @@ qemuMigrationParamsToJSON(qemuMigrationParams *migParams) + if (!pv->set) + continue; + +- switch (qemuMigrationParamTypes[i]) { ++ switch (qemuMigrationParamInfo[i].type) { + case QEMU_MIGRATION_PARAM_TYPE_INT: + rc = virJSONValueObjectAppendNumberInt(params, name, pv->value.i); + break; +@@ -1280,7 +1311,7 @@ qemuMigrationParamsFormat(virBuffer *buf, + virBufferAsprintf(buf, "value.i); + break; +@@ -1357,7 +1388,7 @@ qemuMigrationParamsParse(xmlXPathContextPtr ctxt, + } + + rc = 0; +- switch (qemuMigrationParamTypes[param]) { ++ switch (qemuMigrationParamInfo[param].type) { + case QEMU_MIGRATION_PARAM_TYPE_INT: + rc = virStrToLong_i(value, NULL, 10, &pv->value.i); + break; +-- +2.35.1 + diff --git a/libvirt.spec b/libvirt.spec index 5d77021..baad87c 100644 --- a/libvirt.spec +++ b/libvirt.spec @@ -231,7 +231,7 @@ Summary: Library providing a simple virtualization API Name: libvirt Version: 8.5.0 -Release: 3%{?dist}%{?extra_release} +Release: 4%{?dist}%{?extra_release} License: LGPLv2+ URL: https://libvirt.org/ @@ -259,6 +259,18 @@ Patch16: libvirt-qemu-don-t-try-to-query-QEMU-about-migration-blockers-during-of Patch17: libvirt-qemu_migration-Acquire-correct-job-in-qemuMigrationSrcIsAllowed.patch Patch18: libvirt-virsh-Require-xpath-for-dumpxml.patch Patch19: libvirt-qemu-skip-hardcoded-hostdev-migration-check-if-QEMU-can-do-it-for-us.patch +Patch20: libvirt-qemu-Pass-migration-flags-to-qemuMigrationParamsApply.patch +Patch21: libvirt-qemu_migration_params-Replace-qemuMigrationParamTypes-array.patch +Patch22: libvirt-qemu_migration-Pass-migParams-to-qemuMigrationSrcResume.patch +Patch23: libvirt-qemu_migration-Apply-max-postcopy-bandwidth-on-post-copy-resume.patch +Patch24: libvirt-qemu-Always-assume-support-for-QEMU_CAPS_MIGRATION_PARAM_XBZRLE_CACHE_SIZE.patch +Patch25: libvirt-qemu_migration-Store-original-migration-params-in-status-XML.patch +Patch26: libvirt-qemu_migration_params-Refactor-qemuMigrationParamsApply.patch +Patch27: libvirt-qemu_migration_params-Refactor-qemuMigrationParamsReset.patch +Patch28: libvirt-qemu_migration_params-Avoid-deadlock-in-qemuMigrationParamsReset.patch +Patch29: libvirt-qemu-Restore-original-memory-locking-limit-on-reconnect.patch +Patch30: libvirt-qemu-Properly-release-job-in-qemuDomainSaveInternal.patch +Patch31: libvirt-qemu-don-t-call-qemuMigrationSrcIsAllowedHostdev-from-qemuMigrationDstPrepareFresh.patch Requires: libvirt-daemon = %{version}-%{release} @@ -2165,6 +2177,20 @@ exit 0 %changelog +* Fri Jul 29 2022 Jiri Denemark - 8.5.0-4 +- qemu: Pass migration flags to qemuMigrationParamsApply (rhbz#2111070) +- qemu_migration_params: Replace qemuMigrationParamTypes array (rhbz#2111070) +- qemu_migration: Pass migParams to qemuMigrationSrcResume (rhbz#2111070) +- qemu_migration: Apply max-postcopy-bandwidth on post-copy resume (rhbz#2111070) +- qemu: Always assume support for QEMU_CAPS_MIGRATION_PARAM_XBZRLE_CACHE_SIZE (rhbz#2107892) +- qemu_migration: Store original migration params in status XML (rhbz#2107892) +- qemu_migration_params: Refactor qemuMigrationParamsApply (rhbz#2107892) +- qemu_migration_params: Refactor qemuMigrationParamsReset (rhbz#2107892) +- qemu_migration_params: Avoid deadlock in qemuMigrationParamsReset (rhbz#2107892) +- qemu: Restore original memory locking limit on reconnect (rhbz#2107424) +- qemu: Properly release job in qemuDomainSaveInternal (rhbz#1497907) +- qemu: don't call qemuMigrationSrcIsAllowedHostdev() from qemuMigrationDstPrepareFresh() (rhbz#1497907) + * Mon Jul 25 2022 Jiri Denemark - 8.5.0-3 - qemu: introduce capability QEMU_CAPS_MIGRATION_BLOCKED_REASONS (rhbz#2092833) - qemu: new function to retrieve migration blocker reasons from QEMU (rhbz#2092833)