libvirt/SOURCES/libvirt-qemu-Fix-migration-with-custom-XML.patch
eabdullin 9fd62ba637 - Fix off-by-one error in udevListInterfacesByStatus
- remote: check for negative array lengths before allocation
- qemu: Fix migration with custom XML
2024-04-30 23:35:32 +03:00

140 lines
5.1 KiB
Diff

From 68a98ee089f39edeb2d07f6268cbbcb12629ee8b Mon Sep 17 00:00:00 2001
Message-ID: <68a98ee089f39edeb2d07f6268cbbcb12629ee8b.1713796876.git.jdenemar@redhat.com>
From: Jiri Denemark <jdenemar@redhat.com>
Date: Tue, 16 Apr 2024 12:57:22 +0200
Subject: [PATCH] qemu: Fix migration with custom XML
Ages ago origCPU in domain private data was introduced to provide
backward compatibility when migrating to an old libvirt, which did not
support fetching updated CPU definition from QEMU. Thus origCPU will
contain the original CPU definition before such update. But only if the
update actually changed anything. Let's always fill origCPU with the
original definition when starting a domain so that we can rely on it
being always set, even if it matches the updated definition.
This fixes migration or save operations with custom domain XML after
commit v10.1.0-88-g14d3517410, which expected origCPU to be always set
to the CPU definition from inactive XML to check features explicitly
requested by a user.
https://issues.redhat.com/browse/RHEL-30622
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Tested-by: Han Han <hhan@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
(cherry picked from commit 4331048257071211fb98c21453b187919d42dae7)
https://issues.redhat.com/browse/RHEL-32654
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
src/qemu/qemu_domain.c | 33 ++++++++++++++++++++-------------
src/qemu/qemu_process.c | 19 +++++++------------
2 files changed, 27 insertions(+), 25 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 1daa53dd1b..341c543280 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -10868,12 +10868,13 @@ virSaveCookieCallbacks virQEMUDriverDomainSaveCookie = {
* @vm: domain which is being started
* @cpu: CPU updated when the domain was running previously (before migration,
* snapshot, or save)
- * @origCPU: where to store the original CPU from vm->def in case @cpu was
- * used instead
+ * @origCPU: where to store the original CPU from vm->def
*
- * Replace the CPU definition with the updated one when QEMU is new enough to
- * allow us to check extra features it is about to enable or disable when
- * starting a domain. The original CPU is stored in @origCPU.
+ * Save the original CPU definition from inactive XML in @origCPU so that we
+ * can safely update it and still be able to check what exactly a user asked
+ * for. The domain definition will either contain a copy of the original CPU
+ * definition or a copy of @cpu in case the domain was already running and
+ * we're just restoring a saved state or preparing for incoming migration.
*
* Returns 0 on success, -1 on error.
*/
@@ -10886,18 +10887,24 @@ qemuDomainUpdateCPU(virDomainObj *vm,
*origCPU = NULL;
- if (!cpu || !vm->def->cpu ||
- !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION) ||
- virCPUDefIsEqual(vm->def->cpu, cpu, false))
+ if (!vm->def->cpu)
return 0;
- if (!(cpu = virCPUDefCopy(cpu)))
- return -1;
+ if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION))
+ return 0;
+
+ /* nothing to do if only topology part of CPU def is used */
+ if (vm->def->cpu->mode == VIR_CPU_MODE_CUSTOM && !vm->def->cpu->model)
+ return 0;
+
+ VIR_DEBUG("Replacing CPU definition");
- VIR_DEBUG("Replacing CPU def with the updated one");
+ *origCPU = g_steal_pointer(&vm->def->cpu);
- *origCPU = vm->def->cpu;
- vm->def->cpu = cpu;
+ if (cpu)
+ vm->def->cpu = virCPUDefCopy(cpu);
+ else
+ vm->def->cpu = virCPUDefCopy(*origCPU);
return 0;
}
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 3563ad215c..b75599de68 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4402,8 +4402,6 @@ qemuProcessUpdateLiveGuestCPU(virDomainObj *vm,
virCPUData *disabled)
{
virDomainDef *def = vm->def;
- qemuDomainObjPrivate *priv = vm->privateData;
- g_autoptr(virCPUDef) orig = NULL;
int rc;
if (!enabled)
@@ -4414,19 +4412,11 @@ qemuProcessUpdateLiveGuestCPU(virDomainObj *vm,
!def->cpu->model))
return 0;
- orig = virCPUDefCopy(def->cpu);
-
- if ((rc = virCPUUpdateLive(def->os.arch, def->cpu, enabled, disabled)) < 0) {
+ if ((rc = virCPUUpdateLive(def->os.arch, def->cpu, enabled, disabled)) < 0)
return -1;
- } else if (rc == 0) {
- /* Store the original CPU in priv if QEMU changed it and we didn't
- * get the original CPU via migration, restore, or snapshot revert.
- */
- if (!priv->origCPU && !virCPUDefIsEqual(def->cpu, orig, false))
- priv->origCPU = g_steal_pointer(&orig);
+ if (rc == 0)
def->cpu->check = VIR_CPU_CHECK_FULL;
- }
return 0;
}
@@ -9144,6 +9134,11 @@ qemuProcessReconnect(void *opaque)
qemuDomainVcpuPersistOrder(obj->def);
+ /* Make sure the original CPU is always preserved in priv->origCPU. */
+ if (!priv->origCPU &&
+ qemuDomainUpdateCPU(obj, NULL, &priv->origCPU) < 0)
+ goto error;
+
if (qemuProcessRefreshCPU(driver, obj) < 0)
goto error;
--
2.44.0