File 52b7d910-qemu-refresh-capscache-different-kernel.patch of Package libvirt.9596
commit 52b7d910b6b0ceeff50866774adba6efab55b2c0
Author: Jiri Denemark <jdenemar@redhat.com>
Date: Mon Jan 22 11:37:04 2018 +0100
qemu: Refresh caps cache after booting a different kernel
Whenever a different kernel is booted, some capabilities related to KVM
(such as CPUID bits) may change. We need to refresh the cache to see the
changes.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Index: libvirt-3.3.0/src/qemu/qemu_capabilities.c
===================================================================
--- libvirt-3.3.0.orig/src/qemu/qemu_capabilities.c
+++ libvirt-3.3.0/src/qemu/qemu_capabilities.c
@@ -51,6 +51,7 @@
#include <unistd.h>
#include <sys/wait.h>
#include <stdarg.h>
+#include <sys/utsname.h>
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -422,6 +423,7 @@ struct _virQEMUCaps {
unsigned int kvmVersion;
unsigned int microcodeVersion;
char *package;
+ char *kernelVersion;
virArch arch;
@@ -2204,6 +2206,9 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEM
if (VIR_STRDUP(ret->package, qemuCaps->package) < 0)
goto error;
+ if (VIR_STRDUP(ret->kernelVersion, qemuCaps->kernelVersion) < 0)
+ goto error;
+
ret->arch = qemuCaps->arch;
if (qemuCaps->kvmCPUModels) {
@@ -2264,6 +2269,7 @@ void virQEMUCapsDispose(void *obj)
virBitmapFree(qemuCaps->flags);
VIR_FREE(qemuCaps->package);
+ VIR_FREE(qemuCaps->kernelVersion);
VIR_FREE(qemuCaps->binary);
VIR_FREE(qemuCaps->gicCapabilities);
@@ -3819,6 +3825,12 @@ virQEMUCapsLoadCache(virCapsPtr caps,
goto cleanup;
}
+ if (virXPathBoolean("boolean(./kernelVersion)", ctxt) > 0) {
+ qemuCaps->kernelVersion = virXPathString("string(./kernelVersion)", ctxt);
+ if (!qemuCaps->kernelVersion)
+ goto cleanup;
+ }
+
if (!(str = virXPathString("string(./arch)", ctxt))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("missing arch in QEMU capabilities cache"));
@@ -4085,6 +4097,10 @@ virQEMUCapsFormatCache(virQEMUCapsPtr qe
virBufferAsprintf(&buf, "<package>%s</package>\n",
qemuCaps->package);
+ if (qemuCaps->kernelVersion)
+ virBufferAsprintf(&buf, "<kernelVersion>%s</kernelVersion>\n",
+ qemuCaps->kernelVersion);
+
virBufferAsprintf(&buf, "<arch>%s</arch>\n",
virArchToString(qemuCaps->arch));
@@ -4235,7 +4251,8 @@ virQEMUCapsInitCached(virCapsPtr caps,
const char *cacheDir,
uid_t runUid,
gid_t runGid,
- unsigned int microcodeVersion)
+ unsigned int microcodeVersion,
+ const char *kernelVersion)
{
char *capsdir = NULL;
char *capsfile = NULL;
@@ -4285,7 +4302,7 @@ virQEMUCapsInitCached(virCapsPtr caps,
goto discard;
}
- if (!virQEMUCapsIsValid(qemuCaps, qemuctime, runUid, runGid, microcodeVersion))
+ if (!virQEMUCapsIsValid(qemuCaps, qemuctime, runUid, runGid, microcodeVersion, kernelVersion))
goto discard;
/* Discard cache if QEMU binary or libvirtd changed */
@@ -5134,6 +5151,7 @@ virQEMUCapsNewForBinaryInternal(virCapsP
uid_t runUid,
gid_t runGid,
unsigned int microcodeVersion,
+ const char *kernelVersion,
bool qmpOnly)
{
virQEMUCapsPtr qemuCaps;
@@ -5170,7 +5188,8 @@ virQEMUCapsNewForBinaryInternal(virCapsP
rv = 0;
else if ((rv = virQEMUCapsInitCached(caps, qemuCaps, cacheDir,
runUid, runGid,
- microcodeVersion)) < 0)
+ microcodeVersion,
+ kernelVersion)) < 0)
goto error;
if (rv == 0) {
@@ -5193,9 +5212,13 @@ virQEMUCapsNewForBinaryInternal(virCapsP
goto error;
}
- if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM))
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM)) {
qemuCaps->microcodeVersion = microcodeVersion;
+ if (VIR_STRDUP(qemuCaps->kernelVersion, kernelVersion) < 0)
+ goto error;
+ }
+
if (cacheDir &&
virQEMUCapsRememberCached(qemuCaps, cacheDir) < 0)
goto error;
@@ -5221,10 +5244,12 @@ virQEMUCapsNewForBinary(virCapsPtr caps,
const char *cacheDir,
uid_t runUid,
gid_t runGid,
- unsigned int microcodeVersion)
+ unsigned int microcodeVersion,
+ const char *kernelVersion)
{
return virQEMUCapsNewForBinaryInternal(caps, binary, libDir, cacheDir,
- runUid, runGid, microcodeVersion, false);
+ runUid, runGid, microcodeVersion,
+ kernelVersion, false);
}
@@ -5233,7 +5258,8 @@ virQEMUCapsIsValid(virQEMUCapsPtr qemuCa
time_t qemuctime,
uid_t runUid,
gid_t runGid,
- unsigned int microcodeVersion)
+ unsigned int microcodeVersion,
+ const char *kernelVersion)
{
bool kvmUsable;
@@ -5281,14 +5307,24 @@ virQEMUCapsIsValid(virQEMUCapsPtr qemuCa
return false;
}
- if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM) &&
- microcodeVersion != qemuCaps->microcodeVersion) {
- VIR_DEBUG("Outdated capabilities for '%s': microcode version changed "
- "(%u vs %u)",
- qemuCaps->binary,
- microcodeVersion,
- qemuCaps->microcodeVersion);
- return false;
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM)) {
+ if (microcodeVersion != qemuCaps->microcodeVersion) {
+ VIR_DEBUG("Outdated capabilities for '%s': microcode version "
+ "changed (%u vs %u)",
+ qemuCaps->binary,
+ microcodeVersion,
+ qemuCaps->microcodeVersion);
+ return false;
+ }
+
+ if (STRNEQ_NULLABLE(kernelVersion, qemuCaps->kernelVersion)) {
+ VIR_DEBUG("Outdated capabilities for '%s': kernel version changed "
+ "('%s' vs '%s')",
+ qemuCaps->binary,
+ kernelVersion,
+ qemuCaps->kernelVersion);
+ return false;
+ }
}
return true;
@@ -5341,6 +5377,7 @@ virQEMUCapsCacheNew(const char *libDir,
unsigned int microcodeVersion)
{
virQEMUCapsCachePtr cache;
+ struct utsname uts;
if (VIR_ALLOC(cache) < 0)
return NULL;
@@ -5362,6 +5399,9 @@ virQEMUCapsCacheNew(const char *libDir,
cache->runUid = runUid;
cache->runGid = runGid;
cache->microcodeVersion = microcodeVersion;
+ if (uname(&uts) == 0 &&
+ virAsprintf(&cache->kernelVersion, "%s %s", uts.release, uts.version) < 0)
+ goto error;
return cache;
@@ -5379,7 +5419,7 @@ virQEMUCapsCacheValidate(virQEMUCapsCach
{
if (*qemuCaps &&
!virQEMUCapsIsValid(*qemuCaps, 0, cache->runUid, cache->runGid,
- cache->microcodeVersion)) {
+ cache->microcodeVersion, cache->kernelVersion)) {
VIR_DEBUG("Cached capabilities %p no longer valid for %s",
*qemuCaps, binary);
virHashRemoveEntry(cache->binaries, binary);
@@ -5391,7 +5431,8 @@ virQEMUCapsCacheValidate(virQEMUCapsCach
*qemuCaps = virQEMUCapsNewForBinary(caps, binary,
cache->libDir, cache->cacheDir,
cache->runUid, cache->runGid,
- cache->microcodeVersion);
+ cache->microcodeVersion,
+ cache->kernelVersion);
if (*qemuCaps) {
VIR_DEBUG("Caching capabilities %p for %s", *qemuCaps, binary);
if (virHashAddEntry(cache->binaries, binary, *qemuCaps) < 0) {
Index: libvirt-3.3.0/src/qemu/qemu_capspriv.h
===================================================================
--- libvirt-3.3.0.orig/src/qemu/qemu_capspriv.h
+++ libvirt-3.3.0/src/qemu/qemu_capspriv.h
@@ -36,6 +36,7 @@ struct _virQEMUCapsCache {
uid_t runUid;
gid_t runGid;
unsigned int microcodeVersion;
+ char *kernelVersion;
};
virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps);
@@ -48,6 +49,7 @@ virQEMUCapsNewForBinaryInternal(virCapsP
uid_t runUid,
gid_t runGid,
unsigned int microcodeVersion,
+ const char *kernelVersion,
bool qmpOnly);
int virQEMUCapsLoadCache(virCapsPtr caps,
Index: libvirt-3.3.0/tests/qemucapsprobe.c
===================================================================
--- libvirt-3.3.0.orig/tests/qemucapsprobe.c
+++ libvirt-3.3.0/tests/qemucapsprobe.c
@@ -71,7 +71,7 @@ main(int argc, char **argv)
return EXIT_FAILURE;
if (!(caps = virQEMUCapsNewForBinaryInternal(NULL, argv[1], "/tmp", NULL,
- -1, -1, 0, true)))
+ -1, -1, 0, NULL, true)))
return EXIT_FAILURE;
virObjectUnref(caps);
Index: libvirt-3.3.0/src/qemu/qemu_capabilities.h
===================================================================
--- libvirt-3.3.0.orig/src/qemu/qemu_capabilities.h
+++ libvirt-3.3.0/src/qemu/qemu_capabilities.h
@@ -491,7 +491,8 @@ bool virQEMUCapsIsValid(virQEMUCapsPtr q
time_t ctime,
uid_t runUid,
gid_t runGid,
- unsigned int microcodeVersion);
+ unsigned int microcodeVersion,
+ const char *kernelVersion);
void virQEMUCapsFilterByMachineType(virQEMUCapsPtr qemuCaps,
const char *machineType);