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);
openSUSE Build Service is sponsored by