|
|
c1c534 |
From 098f56f335241d20ed220d8bb245a0dc9ab5fc39 Mon Sep 17 00:00:00 2001
|
|
|
c1c534 |
Message-Id: <098f56f335241d20ed220d8bb245a0dc9ab5fc39@dist-git>
|
|
|
c1c534 |
From: Jiri Denemark <jdenemar@redhat.com>
|
|
|
c1c534 |
Date: Mon, 22 Jan 2018 11:37:04 +0100
|
|
|
c1c534 |
Subject: [PATCH] qemu: Refresh caps cache after booting a different kernel
|
|
|
c1c534 |
|
|
|
c1c534 |
Whenever a different kernel is booted, some capabilities related to KVM
|
|
|
c1c534 |
(such as CPUID bits) may change. We need to refresh the cache to see the
|
|
|
c1c534 |
changes.
|
|
|
c1c534 |
|
|
|
c1c534 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
c1c534 |
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
|
|
|
c1c534 |
(cherry picked from commit 52b7d910b6b0ceeff50866774adba6efab55b2c0)
|
|
|
c1c534 |
|
|
|
c1c534 |
https://bugzilla.redhat.com/show_bug.cgi?id=1525182
|
|
|
c1c534 |
|
|
|
c1c534 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
c1c534 |
---
|
|
|
c1c534 |
src/qemu/qemu_capabilities.c | 57 +++++++++++++++++++++++++++++++++++++-------
|
|
|
c1c534 |
src/qemu/qemu_capspriv.h | 1 +
|
|
|
c1c534 |
tests/qemucapsprobe.c | 2 +-
|
|
|
c1c534 |
3 files changed, 50 insertions(+), 10 deletions(-)
|
|
|
c1c534 |
|
|
|
c1c534 |
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
|
|
|
c1c534 |
index 09323d2580..af4875f82e 100644
|
|
|
c1c534 |
--- a/src/qemu/qemu_capabilities.c
|
|
|
c1c534 |
+++ b/src/qemu/qemu_capabilities.c
|
|
|
c1c534 |
@@ -52,6 +52,7 @@
|
|
|
c1c534 |
#include <unistd.h>
|
|
|
c1c534 |
#include <sys/wait.h>
|
|
|
c1c534 |
#include <stdarg.h>
|
|
|
c1c534 |
+#include <sys/utsname.h>
|
|
|
c1c534 |
|
|
|
c1c534 |
#define VIR_FROM_THIS VIR_FROM_QEMU
|
|
|
c1c534 |
|
|
|
c1c534 |
@@ -509,6 +510,7 @@ struct _virQEMUCaps {
|
|
|
c1c534 |
unsigned int libvirtVersion;
|
|
|
c1c534 |
unsigned int microcodeVersion;
|
|
|
c1c534 |
char *package;
|
|
|
c1c534 |
+ char *kernelVersion;
|
|
|
c1c534 |
|
|
|
c1c534 |
virArch arch;
|
|
|
c1c534 |
|
|
|
c1c534 |
@@ -2302,6 +2304,9 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps)
|
|
|
c1c534 |
if (VIR_STRDUP(ret->package, qemuCaps->package) < 0)
|
|
|
c1c534 |
goto error;
|
|
|
c1c534 |
|
|
|
c1c534 |
+ if (VIR_STRDUP(ret->kernelVersion, qemuCaps->kernelVersion) < 0)
|
|
|
c1c534 |
+ goto error;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
ret->arch = qemuCaps->arch;
|
|
|
c1c534 |
|
|
|
c1c534 |
if (qemuCaps->kvmCPUModels) {
|
|
|
c1c534 |
@@ -2362,6 +2367,7 @@ void virQEMUCapsDispose(void *obj)
|
|
|
c1c534 |
virBitmapFree(qemuCaps->flags);
|
|
|
c1c534 |
|
|
|
c1c534 |
VIR_FREE(qemuCaps->package);
|
|
|
c1c534 |
+ VIR_FREE(qemuCaps->kernelVersion);
|
|
|
c1c534 |
VIR_FREE(qemuCaps->binary);
|
|
|
c1c534 |
|
|
|
c1c534 |
VIR_FREE(qemuCaps->gicCapabilities);
|
|
|
c1c534 |
@@ -3822,6 +3828,7 @@ struct _virQEMUCapsCachePriv {
|
|
|
c1c534 |
gid_t runGid;
|
|
|
c1c534 |
virArch hostArch;
|
|
|
c1c534 |
unsigned int microcodeVersion;
|
|
|
c1c534 |
+ char *kernelVersion;
|
|
|
c1c534 |
};
|
|
|
c1c534 |
typedef struct _virQEMUCapsCachePriv virQEMUCapsCachePriv;
|
|
|
c1c534 |
typedef virQEMUCapsCachePriv *virQEMUCapsCachePrivPtr;
|
|
|
c1c534 |
@@ -3833,6 +3840,7 @@ virQEMUCapsCachePrivFree(void *privData)
|
|
|
c1c534 |
virQEMUCapsCachePrivPtr priv = privData;
|
|
|
c1c534 |
|
|
|
c1c534 |
VIR_FREE(priv->libDir);
|
|
|
c1c534 |
+ VIR_FREE(priv->kernelVersion);
|
|
|
c1c534 |
VIR_FREE(priv);
|
|
|
c1c534 |
}
|
|
|
c1c534 |
|
|
|
c1c534 |
@@ -3958,6 +3966,12 @@ virQEMUCapsLoadCache(virArch hostArch,
|
|
|
c1c534 |
goto cleanup;
|
|
|
c1c534 |
}
|
|
|
c1c534 |
|
|
|
c1c534 |
+ if (virXPathBoolean("boolean(./kernelVersion)", ctxt) > 0) {
|
|
|
c1c534 |
+ qemuCaps->kernelVersion = virXPathString("string(./kernelVersion)", ctxt);
|
|
|
c1c534 |
+ if (!qemuCaps->kernelVersion)
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+
|
|
|
c1c534 |
if (!(str = virXPathString("string(./arch)", ctxt))) {
|
|
|
c1c534 |
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
c1c534 |
_("missing arch in QEMU capabilities cache"));
|
|
|
c1c534 |
@@ -4236,6 +4250,10 @@ virQEMUCapsFormatCache(virQEMUCapsPtr qemuCaps)
|
|
|
c1c534 |
virBufferAsprintf(&buf, "<package>%s</package>\n",
|
|
|
c1c534 |
qemuCaps->package);
|
|
|
c1c534 |
|
|
|
c1c534 |
+ if (qemuCaps->kernelVersion)
|
|
|
c1c534 |
+ virBufferAsprintf(&buf, "<kernelVersion>%s</kernelVersion>\n",
|
|
|
c1c534 |
+ qemuCaps->kernelVersion);
|
|
|
c1c534 |
+
|
|
|
c1c534 |
virBufferAsprintf(&buf, "<arch>%s</arch>\n",
|
|
|
c1c534 |
virArchToString(qemuCaps->arch));
|
|
|
c1c534 |
|
|
|
c1c534 |
@@ -4373,14 +4391,24 @@ virQEMUCapsIsValid(void *data,
|
|
|
c1c534 |
return false;
|
|
|
c1c534 |
}
|
|
|
c1c534 |
|
|
|
c1c534 |
- if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM) &&
|
|
|
c1c534 |
- priv->microcodeVersion != qemuCaps->microcodeVersion) {
|
|
|
c1c534 |
- VIR_DEBUG("Outdated capabilities for '%s': microcode version changed "
|
|
|
c1c534 |
- "(%u vs %u)",
|
|
|
c1c534 |
- qemuCaps->binary,
|
|
|
c1c534 |
- priv->microcodeVersion,
|
|
|
c1c534 |
- qemuCaps->microcodeVersion);
|
|
|
c1c534 |
- return false;
|
|
|
c1c534 |
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM)) {
|
|
|
c1c534 |
+ if (priv->microcodeVersion != qemuCaps->microcodeVersion) {
|
|
|
c1c534 |
+ VIR_DEBUG("Outdated capabilities for '%s': microcode version "
|
|
|
c1c534 |
+ "changed (%u vs %u)",
|
|
|
c1c534 |
+ qemuCaps->binary,
|
|
|
c1c534 |
+ priv->microcodeVersion,
|
|
|
c1c534 |
+ qemuCaps->microcodeVersion);
|
|
|
c1c534 |
+ return false;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (STRNEQ_NULLABLE(priv->kernelVersion, qemuCaps->kernelVersion)) {
|
|
|
c1c534 |
+ VIR_DEBUG("Outdated capabilities for '%s': kernel version changed "
|
|
|
c1c534 |
+ "('%s' vs '%s')",
|
|
|
c1c534 |
+ qemuCaps->binary,
|
|
|
c1c534 |
+ priv->kernelVersion,
|
|
|
c1c534 |
+ qemuCaps->kernelVersion);
|
|
|
c1c534 |
+ return false;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
}
|
|
|
c1c534 |
|
|
|
c1c534 |
return true;
|
|
|
c1c534 |
@@ -5213,6 +5241,7 @@ virQEMUCapsNewForBinaryInternal(virArch hostArch,
|
|
|
c1c534 |
uid_t runUid,
|
|
|
c1c534 |
gid_t runGid,
|
|
|
c1c534 |
unsigned int microcodeVersion,
|
|
|
c1c534 |
+ const char *kernelVersion,
|
|
|
c1c534 |
bool qmpOnly)
|
|
|
c1c534 |
{
|
|
|
c1c534 |
virQEMUCapsPtr qemuCaps;
|
|
|
c1c534 |
@@ -5269,9 +5298,13 @@ virQEMUCapsNewForBinaryInternal(virArch hostArch,
|
|
|
c1c534 |
virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_KVM);
|
|
|
c1c534 |
virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_QEMU);
|
|
|
c1c534 |
|
|
|
c1c534 |
- if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM))
|
|
|
c1c534 |
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM)) {
|
|
|
c1c534 |
qemuCaps->microcodeVersion = microcodeVersion;
|
|
|
c1c534 |
|
|
|
c1c534 |
+ if (VIR_STRDUP(qemuCaps->kernelVersion, kernelVersion) < 0)
|
|
|
c1c534 |
+ goto error;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+
|
|
|
c1c534 |
cleanup:
|
|
|
c1c534 |
VIR_FREE(qmperr);
|
|
|
c1c534 |
return qemuCaps;
|
|
|
c1c534 |
@@ -5294,6 +5327,7 @@ virQEMUCapsNewData(const char *binary,
|
|
|
c1c534 |
priv->runUid,
|
|
|
c1c534 |
priv->runGid,
|
|
|
c1c534 |
priv->microcodeVersion,
|
|
|
c1c534 |
+ priv->kernelVersion,
|
|
|
c1c534 |
false);
|
|
|
c1c534 |
}
|
|
|
c1c534 |
|
|
|
c1c534 |
@@ -5382,6 +5416,7 @@ virQEMUCapsCacheNew(const char *libDir,
|
|
|
c1c534 |
char *capsCacheDir = NULL;
|
|
|
c1c534 |
virFileCachePtr cache = NULL;
|
|
|
c1c534 |
virQEMUCapsCachePrivPtr priv = NULL;
|
|
|
c1c534 |
+ struct utsname uts = { 0 };
|
|
|
c1c534 |
|
|
|
c1c534 |
if (virAsprintf(&capsCacheDir, "%s/capabilities", cacheDir) < 0)
|
|
|
c1c534 |
goto error;
|
|
|
c1c534 |
@@ -5402,6 +5437,10 @@ virQEMUCapsCacheNew(const char *libDir,
|
|
|
c1c534 |
priv->runGid = runGid;
|
|
|
c1c534 |
priv->microcodeVersion = microcodeVersion;
|
|
|
c1c534 |
|
|
|
c1c534 |
+ if (uname(&uts) == 0 &&
|
|
|
c1c534 |
+ virAsprintf(&priv->kernelVersion, "%s %s", uts.release, uts.version) < 0)
|
|
|
c1c534 |
+ goto error;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
cleanup:
|
|
|
c1c534 |
VIR_FREE(capsCacheDir);
|
|
|
c1c534 |
return cache;
|
|
|
c1c534 |
diff --git a/src/qemu/qemu_capspriv.h b/src/qemu/qemu_capspriv.h
|
|
|
c1c534 |
index 98d163b920..222f3368e3 100644
|
|
|
c1c534 |
--- a/src/qemu/qemu_capspriv.h
|
|
|
c1c534 |
+++ b/src/qemu/qemu_capspriv.h
|
|
|
c1c534 |
@@ -37,6 +37,7 @@ virQEMUCapsNewForBinaryInternal(virArch hostArch,
|
|
|
c1c534 |
uid_t runUid,
|
|
|
c1c534 |
gid_t runGid,
|
|
|
c1c534 |
unsigned int microcodeVersion,
|
|
|
c1c534 |
+ const char *kernelVersion,
|
|
|
c1c534 |
bool qmpOnly);
|
|
|
c1c534 |
|
|
|
c1c534 |
int virQEMUCapsLoadCache(virArch hostArch,
|
|
|
c1c534 |
diff --git a/tests/qemucapsprobe.c b/tests/qemucapsprobe.c
|
|
|
c1c534 |
index a5f5a38b16..7d60246949 100644
|
|
|
c1c534 |
--- a/tests/qemucapsprobe.c
|
|
|
c1c534 |
+++ b/tests/qemucapsprobe.c
|
|
|
c1c534 |
@@ -72,7 +72,7 @@ main(int argc, char **argv)
|
|
|
c1c534 |
return EXIT_FAILURE;
|
|
|
c1c534 |
|
|
|
c1c534 |
if (!(caps = virQEMUCapsNewForBinaryInternal(VIR_ARCH_NONE, argv[1], "/tmp",
|
|
|
c1c534 |
- -1, -1, 0, true)))
|
|
|
c1c534 |
+ -1, -1, 0, NULL, true)))
|
|
|
c1c534 |
return EXIT_FAILURE;
|
|
|
c1c534 |
|
|
|
c1c534 |
virObjectUnref(caps);
|
|
|
c1c534 |
--
|
|
|
c1c534 |
2.16.1
|
|
|
c1c534 |
|