|
|
3e5111 |
From 3b5aa0e6272a4b507034bba3d093734ebd658b3b Mon Sep 17 00:00:00 2001
|
|
|
3e5111 |
Message-Id: <3b5aa0e6272a4b507034bba3d093734ebd658b3b@dist-git>
|
|
|
3e5111 |
From: Jiri Denemark <jdenemar@redhat.com>
|
|
|
3e5111 |
Date: Wed, 31 May 2017 12:34:10 +0200
|
|
|
3e5111 |
Subject: [PATCH] qemu: Use updated CPU when starting QEMU if possible
|
|
|
3e5111 |
|
|
|
3e5111 |
If QEMU is new enough and we have the live updated CPU definition in
|
|
|
3e5111 |
either save or migration cookie, we can use it to enforce ABI. The
|
|
|
3e5111 |
original guest CPU from domain XML will be stored in private data.
|
|
|
3e5111 |
|
|
|
3e5111 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
3e5111 |
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
|
|
|
3e5111 |
(cherry picked from commit 8e34f478137c2a6b5e57e382729bd2776b042301)
|
|
|
3e5111 |
|
|
|
3e5111 |
https://bugzilla.redhat.com/show_bug.cgi?id=1441662
|
|
|
3e5111 |
|
|
|
3e5111 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
3e5111 |
---
|
|
|
3e5111 |
src/qemu/qemu_domain.c | 40 ++++++++++++++++++++++++++++++++++++++++
|
|
|
3e5111 |
src/qemu/qemu_domain.h | 5 +++++
|
|
|
3e5111 |
src/qemu/qemu_driver.c | 30 ++++++++++++++++++++++++------
|
|
|
3e5111 |
src/qemu/qemu_migration.c | 2 +-
|
|
|
3e5111 |
src/qemu/qemu_process.c | 24 ++++++++++++++++++++++--
|
|
|
3e5111 |
src/qemu/qemu_process.h | 2 ++
|
|
|
3e5111 |
6 files changed, 94 insertions(+), 9 deletions(-)
|
|
|
3e5111 |
|
|
|
3e5111 |
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
|
|
|
3e5111 |
index 7897a44634..82dacb3c9c 100644
|
|
|
3e5111 |
--- a/src/qemu/qemu_domain.c
|
|
|
3e5111 |
+++ b/src/qemu/qemu_domain.c
|
|
|
3e5111 |
@@ -9225,3 +9225,43 @@ virSaveCookieCallbacks virQEMUDriverDomainSaveCookie = {
|
|
|
3e5111 |
.parse = qemuDomainSaveCookieParse,
|
|
|
3e5111 |
.format = qemuDomainSaveCookieFormat,
|
|
|
3e5111 |
};
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+/**
|
|
|
3e5111 |
+ * qemuDomainUpdateCPU:
|
|
|
3e5111 |
+ * @vm: domain which is being started
|
|
|
3e5111 |
+ * @cpu: CPU updated when the domain was running previously (before migration,
|
|
|
3e5111 |
+ * snapshot, or save)
|
|
|
3e5111 |
+ * @origCPU: where to store the original CPU from vm->def in case @cpu was
|
|
|
3e5111 |
+ * used instead
|
|
|
3e5111 |
+ *
|
|
|
3e5111 |
+ * Replace the CPU definition with the updated one when QEMU is new enough to
|
|
|
3e5111 |
+ * allow us to check extra features it is about to enable or disable when
|
|
|
3e5111 |
+ * starting a domain. The original CPU is stored in @origCPU.
|
|
|
3e5111 |
+ *
|
|
|
3e5111 |
+ * Returns 0 on success, -1 on error.
|
|
|
3e5111 |
+ */
|
|
|
3e5111 |
+int
|
|
|
3e5111 |
+qemuDomainUpdateCPU(virDomainObjPtr vm,
|
|
|
3e5111 |
+ virCPUDefPtr cpu,
|
|
|
3e5111 |
+ virCPUDefPtr *origCPU)
|
|
|
3e5111 |
+{
|
|
|
3e5111 |
+ qemuDomainObjPrivatePtr priv = vm->privateData;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ *origCPU = NULL;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ if (!cpu || !vm->def->cpu ||
|
|
|
3e5111 |
+ !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION) ||
|
|
|
3e5111 |
+ virCPUDefIsEqual(vm->def->cpu, cpu, false))
|
|
|
3e5111 |
+ return 0;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ if (!(cpu = virCPUDefCopy(cpu)))
|
|
|
3e5111 |
+ return -1;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ VIR_DEBUG("Replacing CPU def with the updated one");
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ *origCPU = vm->def->cpu;
|
|
|
3e5111 |
+ vm->def->cpu = cpu;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ return 0;
|
|
|
3e5111 |
+}
|
|
|
3e5111 |
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
|
|
|
3e5111 |
index 2eea7924fb..d635d2995f 100644
|
|
|
3e5111 |
--- a/src/qemu/qemu_domain.h
|
|
|
3e5111 |
+++ b/src/qemu/qemu_domain.h
|
|
|
3e5111 |
@@ -921,4 +921,9 @@ char *qemuDomainDiskBackingStoreGetName(virDomainDiskDefPtr disk,
|
|
|
3e5111 |
virStorageSourcePtr qemuDomainGetStorageSourceByDevstr(const char *devstr,
|
|
|
3e5111 |
virDomainDefPtr def);
|
|
|
3e5111 |
|
|
|
3e5111 |
+int
|
|
|
3e5111 |
+qemuDomainUpdateCPU(virDomainObjPtr vm,
|
|
|
3e5111 |
+ virCPUDefPtr cpu,
|
|
|
3e5111 |
+ virCPUDefPtr *origCPU);
|
|
|
3e5111 |
+
|
|
|
3e5111 |
#endif /* __QEMU_DOMAIN_H__ */
|
|
|
3e5111 |
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
|
|
|
3e5111 |
index f5c5c302be..5567103c37 100644
|
|
|
3e5111 |
--- a/src/qemu/qemu_driver.c
|
|
|
3e5111 |
+++ b/src/qemu/qemu_driver.c
|
|
|
3e5111 |
@@ -1782,7 +1782,7 @@ static virDomainPtr qemuDomainCreateXML(virConnectPtr conn,
|
|
|
3e5111 |
goto cleanup;
|
|
|
3e5111 |
}
|
|
|
3e5111 |
|
|
|
3e5111 |
- if (qemuProcessStart(conn, driver, vm, QEMU_ASYNC_JOB_START,
|
|
|
3e5111 |
+ if (qemuProcessStart(conn, driver, vm, NULL, QEMU_ASYNC_JOB_START,
|
|
|
3e5111 |
NULL, -1, NULL, NULL,
|
|
|
3e5111 |
VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
|
|
|
3e5111 |
start_flags) < 0) {
|
|
|
3e5111 |
@@ -6500,8 +6500,8 @@ qemuDomainSaveImageStartVM(virConnectPtr conn,
|
|
|
3e5111 |
}
|
|
|
3e5111 |
}
|
|
|
3e5111 |
|
|
|
3e5111 |
- if (qemuProcessStart(conn, driver, vm, asyncJob,
|
|
|
3e5111 |
- "stdio", *fd, path, NULL,
|
|
|
3e5111 |
+ if (qemuProcessStart(conn, driver, vm, cookie ? cookie->cpu : NULL,
|
|
|
3e5111 |
+ asyncJob, "stdio", *fd, path, NULL,
|
|
|
3e5111 |
VIR_NETDEV_VPORT_PROFILE_OP_RESTORE,
|
|
|
3e5111 |
VIR_QEMU_PROCESS_START_PAUSED) == 0)
|
|
|
3e5111 |
restored = true;
|
|
|
3e5111 |
@@ -7118,7 +7118,7 @@ qemuDomainObjStart(virConnectPtr conn,
|
|
|
3e5111 |
}
|
|
|
3e5111 |
}
|
|
|
3e5111 |
|
|
|
3e5111 |
- ret = qemuProcessStart(conn, driver, vm, asyncJob,
|
|
|
3e5111 |
+ ret = qemuProcessStart(conn, driver, vm, NULL, asyncJob,
|
|
|
3e5111 |
NULL, -1, NULL, NULL,
|
|
|
3e5111 |
VIR_NETDEV_VPORT_PROFILE_OP_CREATE, start_flags);
|
|
|
3e5111 |
virDomainAuditStart(vm, "booted", ret >= 0);
|
|
|
3e5111 |
@@ -15295,6 +15295,8 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
|
|
|
3e5111 |
virCapsPtr caps = NULL;
|
|
|
3e5111 |
bool was_running = false;
|
|
|
3e5111 |
bool was_stopped = false;
|
|
|
3e5111 |
+ qemuDomainSaveCookiePtr cookie;
|
|
|
3e5111 |
+ virCPUDefPtr origCPU = NULL;
|
|
|
3e5111 |
|
|
|
3e5111 |
virCheckFlags(VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
|
|
|
3e5111 |
VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED |
|
|
|
3e5111 |
@@ -15400,6 +15402,8 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
|
|
|
3e5111 |
goto endjob;
|
|
|
3e5111 |
}
|
|
|
3e5111 |
|
|
|
3e5111 |
+ cookie = (qemuDomainSaveCookiePtr) snap->def->cookie;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
switch ((virDomainState) snap->def->state) {
|
|
|
3e5111 |
case VIR_DOMAIN_RUNNING:
|
|
|
3e5111 |
case VIR_DOMAIN_PAUSED:
|
|
|
3e5111 |
@@ -15411,6 +15415,15 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
|
|
|
3e5111 |
* to have finer control. */
|
|
|
3e5111 |
if (virDomainObjIsActive(vm)) {
|
|
|
3e5111 |
/* Transitions 5, 6, 8, 9 */
|
|
|
3e5111 |
+ /* Replace the CPU in config and put the original one in priv
|
|
|
3e5111 |
+ * once we're done.
|
|
|
3e5111 |
+ */
|
|
|
3e5111 |
+ if (cookie && cookie->cpu && config->cpu) {
|
|
|
3e5111 |
+ origCPU = config->cpu;
|
|
|
3e5111 |
+ if (!(config->cpu = virCPUDefCopy(cookie->cpu)))
|
|
|
3e5111 |
+ goto endjob;
|
|
|
3e5111 |
+ }
|
|
|
3e5111 |
+
|
|
|
3e5111 |
/* Check for ABI compatibility. We need to do this check against
|
|
|
3e5111 |
* the migratable XML or it will always fail otherwise */
|
|
|
3e5111 |
if (config &&
|
|
|
3e5111 |
@@ -15470,8 +15483,11 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
|
|
|
3e5111 |
* failed loadvm attempt? */
|
|
|
3e5111 |
goto endjob;
|
|
|
3e5111 |
}
|
|
|
3e5111 |
- if (config)
|
|
|
3e5111 |
+ if (config) {
|
|
|
3e5111 |
virDomainObjAssignDef(vm, config, false, NULL);
|
|
|
3e5111 |
+ virCPUDefFree(priv->origCPU);
|
|
|
3e5111 |
+ VIR_STEAL_PTR(priv->origCPU, origCPU);
|
|
|
3e5111 |
+ }
|
|
|
3e5111 |
} else {
|
|
|
3e5111 |
/* Transitions 2, 3 */
|
|
|
3e5111 |
load:
|
|
|
3e5111 |
@@ -15480,6 +15496,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
|
|
|
3e5111 |
virDomainObjAssignDef(vm, config, false, NULL);
|
|
|
3e5111 |
|
|
|
3e5111 |
rc = qemuProcessStart(snapshot->domain->conn, driver, vm,
|
|
|
3e5111 |
+ cookie ? cookie->cpu : NULL,
|
|
|
3e5111 |
QEMU_ASYNC_JOB_START, NULL, -1, NULL, snap,
|
|
|
3e5111 |
VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
|
|
|
3e5111 |
VIR_QEMU_PROCESS_START_PAUSED);
|
|
|
3e5111 |
@@ -15573,7 +15590,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
|
|
|
3e5111 |
start_flags |= paused ? VIR_QEMU_PROCESS_START_PAUSED : 0;
|
|
|
3e5111 |
|
|
|
3e5111 |
qemuDomainEventQueue(driver, event);
|
|
|
3e5111 |
- rc = qemuProcessStart(snapshot->domain->conn, driver, vm,
|
|
|
3e5111 |
+ rc = qemuProcessStart(snapshot->domain->conn, driver, vm, NULL,
|
|
|
3e5111 |
QEMU_ASYNC_JOB_START, NULL, -1, NULL, NULL,
|
|
|
3e5111 |
VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
|
|
|
3e5111 |
start_flags);
|
|
|
3e5111 |
@@ -15645,6 +15662,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
|
|
|
3e5111 |
virObjectUnref(caps);
|
|
|
3e5111 |
virObjectUnref(cfg);
|
|
|
3e5111 |
virNWFilterUnlockFilterUpdates();
|
|
|
3e5111 |
+ virCPUDefFree(origCPU);
|
|
|
3e5111 |
|
|
|
3e5111 |
return ret;
|
|
|
3e5111 |
}
|
|
|
3e5111 |
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
|
|
|
3e5111 |
index c03f1be575..a4540ce3c4 100644
|
|
|
3e5111 |
--- a/src/qemu/qemu_migration.c
|
|
|
3e5111 |
+++ b/src/qemu/qemu_migration.c
|
|
|
3e5111 |
@@ -2650,7 +2650,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
|
|
|
3e5111 |
goto stopjob;
|
|
|
3e5111 |
}
|
|
|
3e5111 |
|
|
|
3e5111 |
- if (qemuProcessInit(driver, vm, QEMU_ASYNC_JOB_MIGRATION_IN,
|
|
|
3e5111 |
+ if (qemuProcessInit(driver, vm, mig->cpu, QEMU_ASYNC_JOB_MIGRATION_IN,
|
|
|
3e5111 |
true, VIR_QEMU_PROCESS_START_AUTODESTROY) < 0)
|
|
|
3e5111 |
goto stopjob;
|
|
|
3e5111 |
stopProcess = true;
|
|
|
3e5111 |
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
|
|
|
3e5111 |
index 79f780ed46..a7abfc720e 100644
|
|
|
3e5111 |
--- a/src/qemu/qemu_process.c
|
|
|
3e5111 |
+++ b/src/qemu/qemu_process.c
|
|
|
3e5111 |
@@ -3946,6 +3946,13 @@ qemuProcessUpdateLiveGuestCPU(virQEMUDriverPtr driver,
|
|
|
3e5111 |
if (qemuProcessVerifyCPUFeatures(def, cpu) < 0)
|
|
|
3e5111 |
goto cleanup;
|
|
|
3e5111 |
|
|
|
3e5111 |
+ /* Don't update the CPU if we already did so when starting a domain
|
|
|
3e5111 |
+ * during migration, restore or snapshot revert. */
|
|
|
3e5111 |
+ if (priv->origCPU) {
|
|
|
3e5111 |
+ ret = 0;
|
|
|
3e5111 |
+ goto cleanup;
|
|
|
3e5111 |
+ }
|
|
|
3e5111 |
+
|
|
|
3e5111 |
if (!(orig = virCPUDefCopy(def->cpu)))
|
|
|
3e5111 |
goto cleanup;
|
|
|
3e5111 |
|
|
|
3e5111 |
@@ -4864,6 +4871,7 @@ qemuProcessStartValidate(virQEMUDriverPtr driver,
|
|
|
3e5111 |
int
|
|
|
3e5111 |
qemuProcessInit(virQEMUDriverPtr driver,
|
|
|
3e5111 |
virDomainObjPtr vm,
|
|
|
3e5111 |
+ virCPUDefPtr updatedCPU,
|
|
|
3e5111 |
qemuDomainAsyncJob asyncJob,
|
|
|
3e5111 |
bool migration,
|
|
|
3e5111 |
unsigned int flags)
|
|
|
3e5111 |
@@ -4872,6 +4880,7 @@ qemuProcessInit(virQEMUDriverPtr driver,
|
|
|
3e5111 |
virCapsPtr caps = NULL;
|
|
|
3e5111 |
qemuDomainObjPrivatePtr priv = vm->privateData;
|
|
|
3e5111 |
int stopFlags;
|
|
|
3e5111 |
+ virCPUDefPtr origCPU = NULL;
|
|
|
3e5111 |
int ret = -1;
|
|
|
3e5111 |
|
|
|
3e5111 |
VIR_DEBUG("vm=%p name=%s id=%d migration=%d",
|
|
|
3e5111 |
@@ -4896,6 +4905,9 @@ qemuProcessInit(virQEMUDriverPtr driver,
|
|
|
3e5111 |
vm->def->os.machine)))
|
|
|
3e5111 |
goto cleanup;
|
|
|
3e5111 |
|
|
|
3e5111 |
+ if (qemuDomainUpdateCPU(vm, updatedCPU, &origCPU) < 0)
|
|
|
3e5111 |
+ goto cleanup;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
if (qemuProcessStartValidate(driver, vm, priv->qemuCaps, caps, flags) < 0)
|
|
|
3e5111 |
goto cleanup;
|
|
|
3e5111 |
|
|
|
3e5111 |
@@ -4928,11 +4940,14 @@ qemuProcessInit(virQEMUDriverPtr driver,
|
|
|
3e5111 |
|
|
|
3e5111 |
if (qemuDomainSetPrivatePaths(driver, vm) < 0)
|
|
|
3e5111 |
goto stop;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ VIR_STEAL_PTR(priv->origCPU, origCPU);
|
|
|
3e5111 |
}
|
|
|
3e5111 |
|
|
|
3e5111 |
ret = 0;
|
|
|
3e5111 |
|
|
|
3e5111 |
cleanup:
|
|
|
3e5111 |
+ virCPUDefFree(origCPU);
|
|
|
3e5111 |
virObjectUnref(cfg);
|
|
|
3e5111 |
virObjectUnref(caps);
|
|
|
3e5111 |
return ret;
|
|
|
3e5111 |
@@ -5963,6 +5978,7 @@ int
|
|
|
3e5111 |
qemuProcessStart(virConnectPtr conn,
|
|
|
3e5111 |
virQEMUDriverPtr driver,
|
|
|
3e5111 |
virDomainObjPtr vm,
|
|
|
3e5111 |
+ virCPUDefPtr updatedCPU,
|
|
|
3e5111 |
qemuDomainAsyncJob asyncJob,
|
|
|
3e5111 |
const char *migrateFrom,
|
|
|
3e5111 |
int migrateFd,
|
|
|
3e5111 |
@@ -5993,7 +6009,8 @@ qemuProcessStart(virConnectPtr conn,
|
|
|
3e5111 |
if (!migrateFrom && !snapshot)
|
|
|
3e5111 |
flags |= VIR_QEMU_PROCESS_START_NEW;
|
|
|
3e5111 |
|
|
|
3e5111 |
- if (qemuProcessInit(driver, vm, asyncJob, !!migrateFrom, flags) < 0)
|
|
|
3e5111 |
+ if (qemuProcessInit(driver, vm, updatedCPU,
|
|
|
3e5111 |
+ asyncJob, !!migrateFrom, flags) < 0)
|
|
|
3e5111 |
goto cleanup;
|
|
|
3e5111 |
|
|
|
3e5111 |
if (migrateFrom) {
|
|
|
3e5111 |
@@ -6072,7 +6089,8 @@ qemuProcessCreatePretendCmd(virConnectPtr conn,
|
|
|
3e5111 |
flags |= VIR_QEMU_PROCESS_START_PRETEND;
|
|
|
3e5111 |
flags |= VIR_QEMU_PROCESS_START_NEW;
|
|
|
3e5111 |
|
|
|
3e5111 |
- if (qemuProcessInit(driver, vm, QEMU_ASYNC_JOB_NONE, !!migrateURI, flags) < 0)
|
|
|
3e5111 |
+ if (qemuProcessInit(driver, vm, NULL, QEMU_ASYNC_JOB_NONE,
|
|
|
3e5111 |
+ !!migrateURI, flags) < 0)
|
|
|
3e5111 |
goto cleanup;
|
|
|
3e5111 |
|
|
|
3e5111 |
if (qemuProcessPrepareDomain(conn, driver, vm, flags) < 0)
|
|
|
3e5111 |
@@ -6474,6 +6492,8 @@ void qemuProcessStop(virQEMUDriverPtr driver,
|
|
|
3e5111 |
|
|
|
3e5111 |
/* clean up migration data */
|
|
|
3e5111 |
VIR_FREE(priv->migTLSAlias);
|
|
|
3e5111 |
+ virCPUDefFree(priv->origCPU);
|
|
|
3e5111 |
+ priv->origCPU = NULL;
|
|
|
3e5111 |
|
|
|
3e5111 |
/* clear previously used namespaces */
|
|
|
3e5111 |
virBitmapFree(priv->namespaces);
|
|
|
3e5111 |
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
|
|
|
3e5111 |
index 830d8cef84..c38310b47a 100644
|
|
|
3e5111 |
--- a/src/qemu/qemu_process.h
|
|
|
3e5111 |
+++ b/src/qemu/qemu_process.h
|
|
|
3e5111 |
@@ -75,6 +75,7 @@ typedef enum {
|
|
|
3e5111 |
int qemuProcessStart(virConnectPtr conn,
|
|
|
3e5111 |
virQEMUDriverPtr driver,
|
|
|
3e5111 |
virDomainObjPtr vm,
|
|
|
3e5111 |
+ virCPUDefPtr updatedCPU,
|
|
|
3e5111 |
qemuDomainAsyncJob asyncJob,
|
|
|
3e5111 |
const char *migrateFrom,
|
|
|
3e5111 |
int stdin_fd,
|
|
|
3e5111 |
@@ -93,6 +94,7 @@ virCommandPtr qemuProcessCreatePretendCmd(virConnectPtr conn,
|
|
|
3e5111 |
|
|
|
3e5111 |
int qemuProcessInit(virQEMUDriverPtr driver,
|
|
|
3e5111 |
virDomainObjPtr vm,
|
|
|
3e5111 |
+ virCPUDefPtr updatedCPU,
|
|
|
3e5111 |
qemuDomainAsyncJob asyncJob,
|
|
|
3e5111 |
bool migration,
|
|
|
3e5111 |
unsigned int flags);
|
|
|
3e5111 |
--
|
|
|
3e5111 |
2.13.1
|
|
|
3e5111 |
|