File 004804a7-qemu-invalidate-caps.patch of Package libvirt.22291
commit 004804a7d77d0b63ce2f5fcb8499c94b77a5ef5c
Author: Jiri Denemark <jdenemar@redhat.com>
Date: Fri May 15 22:00:29 2020 +0200
qemu: Invalidate capabilities when host CPU changes
The host CPU related info stored in the capabilities cache is no longer
valid after the host CPU changes. This is not a frequent situation in
real world, but it can easily happen in nested scenarios when a disk
image is started with various CPUs.
https://bugzilla.redhat.com/show_bug.cgi?id=1778819
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Index: libvirt-6.0.0/src/qemu/qemu_capabilities.c
===================================================================
--- libvirt-6.0.0.orig/src/qemu/qemu_capabilities.c
+++ libvirt-6.0.0/src/qemu/qemu_capabilities.c
@@ -622,6 +622,7 @@ struct _virQEMUCaps {
unsigned int kvmVersion;
unsigned int libvirtVersion;
unsigned int microcodeVersion;
+ char *hostCPUSignature;
char *package;
char *kernelVersion;
@@ -1780,6 +1781,7 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEM
ret->version = qemuCaps->version;
ret->kvmVersion = qemuCaps->kvmVersion;
ret->microcodeVersion = qemuCaps->microcodeVersion;
+ ret->hostCPUSignature = g_strdup(qemuCaps->hostCPUSignature);
ret->package = g_strdup(qemuCaps->package);
ret->kernelVersion = g_strdup(qemuCaps->kernelVersion);
@@ -1836,6 +1838,7 @@ void virQEMUCapsDispose(void *obj)
VIR_FREE(qemuCaps->package);
VIR_FREE(qemuCaps->kernelVersion);
VIR_FREE(qemuCaps->binary);
+ VIR_FREE(qemuCaps->hostCPUSignature);
VIR_FREE(qemuCaps->gicCapabilities);
@@ -3798,6 +3801,7 @@ struct _virQEMUCapsCachePriv {
virArch hostArch;
unsigned int microcodeVersion;
char *kernelVersion;
+ char *hostCPUSignature;
/* cache whether /dev/kvm is usable as runUid:runGuid */
virTristateBool kvmUsable;
@@ -3814,6 +3818,7 @@ virQEMUCapsCachePrivFree(void *privData)
VIR_FREE(priv->libDir);
VIR_FREE(priv->kernelVersion);
+ VIR_FREE(priv->hostCPUSignature);
VIR_FREE(priv);
}
@@ -3991,6 +3996,8 @@ virQEMUCapsLoadCache(virArch hostArch,
goto cleanup;
}
+ qemuCaps->hostCPUSignature = virXPathString("string(./hostCPUSignature)", ctxt);
+
if (virXPathBoolean("boolean(./package)", ctxt) > 0) {
qemuCaps->package = virXPathString("string(./package)", ctxt);
if (!qemuCaps->package)
@@ -4294,6 +4301,8 @@ virQEMUCapsFormatCache(virQEMUCapsPtr qe
virBufferAsprintf(&buf, "<microcodeVersion>%u</microcodeVersion>\n",
qemuCaps->microcodeVersion);
+ virBufferEscapeString(&buf, "<hostCPUSignature>%s</hostCPUSignature>\n",
+ qemuCaps->hostCPUSignature);
if (qemuCaps->package)
virBufferAsprintf(&buf, "<package>%s</package>\n",
@@ -4595,6 +4604,15 @@ virQEMUCapsIsValid(void *data,
}
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM)) {
+ if (STRNEQ_NULLABLE(priv->hostCPUSignature, qemuCaps->hostCPUSignature)) {
+ VIR_DEBUG("Outdated capabilities for '%s': host CPU changed "
+ "('%s' vs '%s')",
+ qemuCaps->binary,
+ priv->hostCPUSignature,
+ qemuCaps->hostCPUSignature);
+ return false;
+ }
+
if (priv->microcodeVersion != qemuCaps->microcodeVersion) {
VIR_DEBUG("Outdated capabilities for '%s': microcode version "
"changed (%u vs %u)",
@@ -5051,6 +5069,7 @@ virQEMUCapsNewForBinaryInternal(virArch
const char *libDir,
uid_t runUid,
gid_t runGid,
+ const char *hostCPUSignature,
unsigned int microcodeVersion,
const char *kernelVersion)
{
@@ -5089,6 +5108,7 @@ virQEMUCapsNewForBinaryInternal(virArch
virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_QEMU);
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM)) {
+ qemuCaps->hostCPUSignature = g_strdup(hostCPUSignature);
qemuCaps->microcodeVersion = microcodeVersion;
qemuCaps->kernelVersion = g_strdup(kernelVersion);
@@ -5116,6 +5136,7 @@ virQEMUCapsNewData(const char *binary,
priv->libDir,
priv->runUid,
priv->runGid,
+ priv->hostCPUSignature,
virHostCPUGetMicrocodeVersion(),
priv->kernelVersion);
}
@@ -5215,6 +5236,9 @@ virQEMUCapsCacheNew(const char *libDir,
priv->hostArch = virArchFromHost();
+ if (virHostCPUGetSignature(&priv->hostCPUSignature) < 0)
+ goto error;
+
priv->runUid = runUid;
priv->runGid = runGid;
priv->kvmUsable = VIR_TRISTATE_BOOL_ABSENT;
Index: libvirt-6.0.0/src/qemu/qemu_capspriv.h
===================================================================
--- libvirt-6.0.0.orig/src/qemu/qemu_capspriv.h
+++ libvirt-6.0.0/src/qemu/qemu_capspriv.h
@@ -33,6 +33,7 @@ virQEMUCapsNewForBinaryInternal(virArch
const char *libDir,
uid_t runUid,
gid_t runGid,
+ const char *hostCPUSignature,
unsigned int microcodeVersion,
const char *kernelVersion);
Index: libvirt-6.0.0/tests/qemucapsprobe.c
===================================================================
--- libvirt-6.0.0.orig/tests/qemucapsprobe.c
+++ libvirt-6.0.0/tests/qemucapsprobe.c
@@ -75,7 +75,7 @@ main(int argc, char **argv)
return EXIT_FAILURE;
if (!(caps = virQEMUCapsNewForBinaryInternal(VIR_ARCH_NONE, argv[1], "/tmp",
- -1, -1, 0, NULL)))
+ -1, -1, NULL, 0, NULL)))
return EXIT_FAILURE;
virObjectUnref(caps);