render / rpms / libvirt

Forked from rpms/libvirt 10 months ago
Clone
a1c947
From b8c791a3fc2767e6d899e3e0c590a93cb0ee7e03 Mon Sep 17 00:00:00 2001
a1c947
Message-Id: <b8c791a3fc2767e6d899e3e0c590a93cb0ee7e03@dist-git>
a1c947
From: Jiri Denemark <jdenemar@redhat.com>
a1c947
Date: Thu, 30 Jun 2022 12:52:38 +0200
a1c947
Subject: [PATCH] qemu_migration: Apply max-postcopy-bandwidth on post-copy
a1c947
 resume
a1c947
a1c947
When resuming post-copy migration users may want to limit the bandwidth
a1c947
used by the migration and use a value that is different from the one
a1c947
specified when the migration was originally started.
a1c947
a1c947
Resolves: https://gitlab.com/libvirt/libvirt/-/issues/333
a1c947
a1c947
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
a1c947
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
a1c947
(cherry picked from commit 766abdc291ba606379a7d197bff477fef25fb508)
a1c947
a1c947
https://bugzilla.redhat.com/show_bug.cgi?id=2111070
a1c947
a1c947
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
a1c947
---
a1c947
 src/qemu/qemu_migration.c            | 12 ++++++--
a1c947
 src/qemu/qemu_migration_params.c     | 45 ++++++++++++++++++----------
a1c947
 src/qemu/qemu_migration_paramspriv.h |  3 +-
a1c947
 tests/qemumigparamstest.c            |  2 +-
a1c947
 tests/qemumigrationcookiexmltest.c   |  2 +-
a1c947
 5 files changed, 42 insertions(+), 22 deletions(-)
a1c947
a1c947
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
a1c947
index 285a49c5ff..8a2f5b09a1 100644
a1c947
--- a/src/qemu/qemu_migration.c
a1c947
+++ b/src/qemu/qemu_migration.c
a1c947
@@ -5097,12 +5097,13 @@ qemuMigrationSrcRun(virQEMUDriver *driver,
a1c947
 
a1c947
 static int
a1c947
 qemuMigrationSrcResume(virDomainObj *vm,
a1c947
-                       qemuMigrationParams *migParams G_GNUC_UNUSED,
a1c947
+                       qemuMigrationParams *migParams,
a1c947
                        const char *cookiein,
a1c947
                        int cookieinlen,
a1c947
                        char **cookieout,
a1c947
                        int *cookieoutlen,
a1c947
-                       qemuMigrationSpec *spec)
a1c947
+                       qemuMigrationSpec *spec,
a1c947
+                       unsigned long flags)
a1c947
 {
a1c947
     qemuDomainObjPrivate *priv = vm->privateData;
a1c947
     virQEMUDriver *driver = priv->driver;
a1c947
@@ -5119,6 +5120,10 @@ qemuMigrationSrcResume(virDomainObj *vm,
a1c947
     if (!mig)
a1c947
         return -1;
a1c947
 
a1c947
+    if (qemuMigrationParamsApply(driver, vm, VIR_ASYNC_JOB_MIGRATION_OUT,
a1c947
+                                 migParams, flags) < 0)
a1c947
+        return -1;
a1c947
+
a1c947
     if (qemuDomainObjEnterMonitorAsync(driver, vm,
a1c947
                                        VIR_ASYNC_JOB_MIGRATION_OUT) < 0)
a1c947
         return -1;
a1c947
@@ -5200,6 +5205,7 @@ qemuMigrationSrcPerformNative(virQEMUDriver *driver,
a1c947
 
a1c947
     if (STREQ(uribits->scheme, "unix")) {
a1c947
         if ((flags & VIR_MIGRATE_TLS) &&
a1c947
+            !(flags & VIR_MIGRATE_POSTCOPY_RESUME) &&
a1c947
             !qemuMigrationParamsTLSHostnameIsSet(migParams)) {
a1c947
             virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
a1c947
                            _("Explicit destination hostname is required "
a1c947
@@ -5231,7 +5237,7 @@ qemuMigrationSrcPerformNative(virQEMUDriver *driver,
a1c947
 
a1c947
     if (flags & VIR_MIGRATE_POSTCOPY_RESUME) {
a1c947
         ret = qemuMigrationSrcResume(vm, migParams, cookiein, cookieinlen,
a1c947
-                                     cookieout, cookieoutlen, &spec);
a1c947
+                                     cookieout, cookieoutlen, &spec, flags);
a1c947
     } else {
a1c947
         ret = qemuMigrationSrcRun(driver, vm, persist_xml, cookiein, cookieinlen,
a1c947
                                   cookieout, cookieoutlen, flags, resource,
a1c947
diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c
a1c947
index a68aed9aa4..6ea0bde13a 100644
a1c947
--- a/src/qemu/qemu_migration_params.c
a1c947
+++ b/src/qemu/qemu_migration_params.c
a1c947
@@ -141,6 +141,7 @@ struct _qemuMigrationParamsTPMapItem {
a1c947
 typedef struct _qemuMigrationParamInfoItem qemuMigrationParamInfoItem;
a1c947
 struct _qemuMigrationParamInfoItem {
a1c947
     qemuMigrationParamType type;
a1c947
+    bool applyOnPostcopyResume;
a1c947
 };
a1c947
 
a1c947
 /* Migration capabilities which should always be enabled as long as they
a1c947
@@ -265,6 +266,7 @@ static const qemuMigrationParamInfoItem qemuMigrationParamInfo[] = {
a1c947
     },
a1c947
     [QEMU_MIGRATION_PARAM_MAX_POSTCOPY_BANDWIDTH] = {
a1c947
         .type = QEMU_MIGRATION_PARAM_TYPE_ULL,
a1c947
+        .applyOnPostcopyResume = true,
a1c947
     },
a1c947
     [QEMU_MIGRATION_PARAM_MULTIFD_CHANNELS] = {
a1c947
         .type = QEMU_MIGRATION_PARAM_TYPE_INT,
a1c947
@@ -782,7 +784,8 @@ qemuMigrationParamsFromJSON(virJSONValue *params)
a1c947
 
a1c947
 
a1c947
 virJSONValue *
a1c947
-qemuMigrationParamsToJSON(qemuMigrationParams *migParams)
a1c947
+qemuMigrationParamsToJSON(qemuMigrationParams *migParams,
a1c947
+                          bool postcopyResume)
a1c947
 {
a1c947
     g_autoptr(virJSONValue) params = virJSONValueNewObject();
a1c947
     size_t i;
a1c947
@@ -795,6 +798,9 @@ qemuMigrationParamsToJSON(qemuMigrationParams *migParams)
a1c947
         if (!pv->set)
a1c947
             continue;
a1c947
 
a1c947
+        if (postcopyResume && !qemuMigrationParamInfo[i].applyOnPostcopyResume)
a1c947
+            continue;
a1c947
+
a1c947
         switch (qemuMigrationParamInfo[i].type) {
a1c947
         case QEMU_MIGRATION_PARAM_TYPE_INT:
a1c947
             rc = virJSONValueObjectAppendNumberInt(params, name, pv->value.i);
a1c947
@@ -868,6 +874,7 @@ qemuMigrationCapsToJSON(virBitmap *caps,
a1c947
  *
a1c947
  * Send parameters stored in @migParams to QEMU. If @apiFlags is non-zero, some
a1c947
  * parameters that do not make sense for the enabled flags will be ignored.
a1c947
+ * VIR_MIGRATE_POSTCOPY_RESUME is the only flag checked currently.
a1c947
  *
a1c947
  * Returns 0 on success, -1 on failure.
a1c947
  */
a1c947
@@ -876,32 +883,38 @@ qemuMigrationParamsApply(virQEMUDriver *driver,
a1c947
                          virDomainObj *vm,
a1c947
                          int asyncJob,
a1c947
                          qemuMigrationParams *migParams,
a1c947
-                         unsigned long apiFlags G_GNUC_UNUSED)
a1c947
+                         unsigned long apiFlags)
a1c947
 {
a1c947
     qemuDomainObjPrivate *priv = vm->privateData;
a1c947
     bool xbzrleCacheSize_old = false;
a1c947
     g_autoptr(virJSONValue) params = NULL;
a1c947
     g_autoptr(virJSONValue) caps = NULL;
a1c947
     qemuMigrationParam xbzrle = QEMU_MIGRATION_PARAM_XBZRLE_CACHE_SIZE;
a1c947
+    bool postcopyResume = !!(apiFlags & VIR_MIGRATE_POSTCOPY_RESUME);
a1c947
     int ret = -1;
a1c947
 
a1c947
     if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
a1c947
         return -1;
a1c947
 
a1c947
-    if (asyncJob == VIR_ASYNC_JOB_NONE) {
a1c947
-        if (!virBitmapIsAllClear(migParams->caps)) {
a1c947
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
a1c947
-                           _("Migration capabilities can only be set by "
a1c947
-                             "a migration job"));
a1c947
-            goto cleanup;
a1c947
-        }
a1c947
-    } else {
a1c947
-        if (!(caps = qemuMigrationCapsToJSON(priv->migrationCaps, migParams->caps)))
a1c947
-            goto cleanup;
a1c947
+    /* Changing capabilities is only allowed before migration starts, we need
a1c947
+     * to skip them when resuming post-copy migration.
a1c947
+     */
a1c947
+    if (!postcopyResume) {
a1c947
+        if (asyncJob == VIR_ASYNC_JOB_NONE) {
a1c947
+            if (!virBitmapIsAllClear(migParams->caps)) {
a1c947
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
a1c947
+                               _("Migration capabilities can only be set by "
a1c947
+                                 "a migration job"));
a1c947
+                goto cleanup;
a1c947
+            }
a1c947
+        } else {
a1c947
+            if (!(caps = qemuMigrationCapsToJSON(priv->migrationCaps, migParams->caps)))
a1c947
+                goto cleanup;
a1c947
 
a1c947
-        if (virJSONValueArraySize(caps) > 0 &&
a1c947
-            qemuMonitorSetMigrationCapabilities(priv->mon, &caps) < 0)
a1c947
-            goto cleanup;
a1c947
+            if (virJSONValueArraySize(caps) > 0 &&
a1c947
+                qemuMonitorSetMigrationCapabilities(priv->mon, &caps) < 0)
a1c947
+                goto cleanup;
a1c947
+        }
a1c947
     }
a1c947
 
a1c947
     /* If QEMU is too old to support xbzrle-cache-size migration parameter,
a1c947
@@ -917,7 +930,7 @@ qemuMigrationParamsApply(virQEMUDriver *driver,
a1c947
         migParams->params[xbzrle].set = false;
a1c947
     }
a1c947
 
a1c947
-    if (!(params = qemuMigrationParamsToJSON(migParams)))
a1c947
+    if (!(params = qemuMigrationParamsToJSON(migParams, postcopyResume)))
a1c947
         goto cleanup;
a1c947
 
a1c947
     if (virJSONValueObjectKeysNumber(params) > 0 &&
a1c947
diff --git a/src/qemu/qemu_migration_paramspriv.h b/src/qemu/qemu_migration_paramspriv.h
a1c947
index f7e0f51fbd..34d51231ff 100644
a1c947
--- a/src/qemu/qemu_migration_paramspriv.h
a1c947
+++ b/src/qemu/qemu_migration_paramspriv.h
a1c947
@@ -26,7 +26,8 @@
a1c947
 #pragma once
a1c947
 
a1c947
 virJSONValue *
a1c947
-qemuMigrationParamsToJSON(qemuMigrationParams *migParams);
a1c947
+qemuMigrationParamsToJSON(qemuMigrationParams *migParams,
a1c947
+                          bool postcopyResume);
a1c947
 
a1c947
 qemuMigrationParams *
a1c947
 qemuMigrationParamsFromJSON(virJSONValue *params);
a1c947
diff --git a/tests/qemumigparamstest.c b/tests/qemumigparamstest.c
a1c947
index bcdee5f32b..5d45a9dd58 100644
a1c947
--- a/tests/qemumigparamstest.c
a1c947
+++ b/tests/qemumigparamstest.c
a1c947
@@ -155,7 +155,7 @@ qemuMigParamsTestJSON(const void *opaque)
a1c947
     if (!(migParams = qemuMigrationParamsFromJSON(paramsIn)))
a1c947
         return -1;
a1c947
 
a1c947
-    if (!(paramsOut = qemuMigrationParamsToJSON(migParams)) ||
a1c947
+    if (!(paramsOut = qemuMigrationParamsToJSON(migParams, false)) ||
a1c947
         !(actualJSON = virJSONValueToString(paramsOut, true)))
a1c947
         return -1;
a1c947
 
a1c947
diff --git a/tests/qemumigrationcookiexmltest.c b/tests/qemumigrationcookiexmltest.c
a1c947
index 316bfedd15..9731348b53 100644
a1c947
--- a/tests/qemumigrationcookiexmltest.c
a1c947
+++ b/tests/qemumigrationcookiexmltest.c
a1c947
@@ -333,7 +333,7 @@ testQemuMigrationCookieBlockDirtyBitmaps(const void *opaque)
a1c947
 
a1c947
     qemuMigrationParamsSetBlockDirtyBitmapMapping(migParams, &migParamsBitmaps);
a1c947
 
a1c947
-    if (!(paramsOut = qemuMigrationParamsToJSON(migParams)) ||
a1c947
+    if (!(paramsOut = qemuMigrationParamsToJSON(migParams, false)) ||
a1c947
         !(actualJSON = virJSONValueToString(paramsOut, true)))
a1c947
         return -1;
a1c947
 
a1c947
-- 
a1c947
2.35.1
a1c947