[libvirt PATCH 0/4] qemu_migration: Apply max-postcopy-bandwidth on post-copy resume

Resolves: https://gitlab.com/libvirt/libvirt/-/issues/333 Jiri Denemark (4): qemu: Pass migration flags to qemuMigrationParamsApply qemu_migration_params: Replace qemuMigrationParamTypes array qemu_migration: Pass migParams to qemuMigrationSrcResume qemu_migration: Apply max-postcopy-bandwidth on post-copy resume src/qemu/qemu_driver.c | 6 +- src/qemu/qemu_migration.c | 26 ++++-- src/qemu/qemu_migration_params.c | 131 ++++++++++++++++++--------- src/qemu/qemu_migration_params.h | 3 +- src/qemu/qemu_migration_paramspriv.h | 3 +- tests/qemumigparamstest.c | 2 +- tests/qemumigrationcookiexmltest.c | 2 +- 7 files changed, 116 insertions(+), 57 deletions(-) -- 2.35.1

The flags will later be used to determine which parameters should actually be applied. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- 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 3b5c3db67c..97c6ed95af 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -13078,7 +13078,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); @@ -13260,7 +13260,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); @@ -13347,7 +13347,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 9a10ce4abe..4ca2f8b600 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -3213,7 +3213,7 @@ qemuMigrationDstPrepareActive(virQEMUDriver *driver, } if (qemuMigrationParamsApply(driver, vm, VIR_ASYNC_JOB_MIGRATION_IN, - migParams) < 0) + migParams, flags) < 0) goto error; if (mig->nbd && @@ -4801,7 +4801,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) { @@ -6895,7 +6895,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; @@ -6991,7 +6991,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

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 <jdenemar@redhat.com> --- 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, "<param name='%s' ", qemuMigrationParamTypeToString(i)); - switch (qemuMigrationParamTypes[i]) { + switch (qemuMigrationParamInfo[i].type) { case QEMU_MIGRATION_PARAM_TYPE_INT: virBufferAsprintf(buf, "value='%d'", pv->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

So the we can apply selected migration parameters even when resuming post-copy migration. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- 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 4ca2f8b600..0c41af86e7 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -5051,6 +5051,7 @@ qemuMigrationSrcRun(virQEMUDriver *driver, static int qemuMigrationSrcResume(virDomainObj *vm, + qemuMigrationParams *migParams G_GNUC_UNUSED, const char *cookiein, int cookieinlen, char **cookieout, @@ -5183,7 +5184,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, @@ -6078,6 +6079,7 @@ qemuMigrationSrcPerformResume(virQEMUDriver *driver, virConnectPtr conn, virDomainObj *vm, const char *uri, + qemuMigrationParams *migParams, const char *cookiein, int cookieinlen, char **cookieout, @@ -6102,7 +6104,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) @@ -6142,7 +6144,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

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 <jdenemar@redhat.com> --- 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 0c41af86e7..368995085f 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -5051,12 +5051,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; @@ -5073,6 +5074,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; @@ -5154,6 +5159,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 " @@ -5185,7 +5191,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

On 6/30/22 13:45, Jiri Denemark wrote:
Resolves: https://gitlab.com/libvirt/libvirt/-/issues/333
Jiri Denemark (4): qemu: Pass migration flags to qemuMigrationParamsApply qemu_migration_params: Replace qemuMigrationParamTypes array qemu_migration: Pass migParams to qemuMigrationSrcResume qemu_migration: Apply max-postcopy-bandwidth on post-copy resume
src/qemu/qemu_driver.c | 6 +- src/qemu/qemu_migration.c | 26 ++++-- src/qemu/qemu_migration_params.c | 131 ++++++++++++++++++--------- src/qemu/qemu_migration_params.h | 3 +- src/qemu/qemu_migration_paramspriv.h | 3 +- tests/qemumigparamstest.c | 2 +- tests/qemumigrationcookiexmltest.c | 2 +- 7 files changed, 116 insertions(+), 57 deletions(-)
Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Michal
participants (2)
-
Jiri Denemark
-
Michal Prívozník