render / rpms / libvirt

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