[libvirt] [PATCH v3 02/20] Switch over to use cache for building QEMU capabilities

Daniel P. Berrange berrange at redhat.com
Tue Sep 25 17:59:55 UTC 2012


From: "Daniel P. Berrange" <berrange at redhat.com>

When building up a virCapsPtr instance, the QEMU driver
was copying the list of machine types across from the
previous virCapsPtr instance, if the QEMU binary had not
changed. Replace this ad-hoc caching of data with use
of the new qemuCapsCache global cache.

Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
---
 src/conf/capabilities.h      |   1 -
 src/qemu/qemu_capabilities.c | 228 +++++++++++++------------------------------
 src/qemu/qemu_capabilities.h |   7 +-
 src/qemu/qemu_conf.h         |   2 +
 src/qemu/qemu_driver.c       |  15 +--
 5 files changed, 84 insertions(+), 169 deletions(-)

diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h
index b7c9f6c..0d56290 100644
--- a/src/conf/capabilities.h
+++ b/src/conf/capabilities.h
@@ -53,7 +53,6 @@ struct _virCapsGuestDomainInfo {
     char *loader;
     int nmachines;
     virCapsGuestMachinePtr *machines;
-    time_t emulator_mtime; /* do @machines need refreshing? */
 };
 
 typedef struct _virCapsGuestDomain virCapsGuestDomain;
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 1163dd8..cb5f63b 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -411,97 +411,6 @@ cleanup:
     return ret;
 }
 
-static int
-qemuCapsGetOldMachinesFromInfo(virCapsGuestDomainInfoPtr info,
-                               const char *emulator,
-                               time_t emulator_mtime,
-                               virCapsGuestMachinePtr **machines,
-                               size_t *nmachines)
-{
-    virCapsGuestMachinePtr *list;
-    int i;
-
-    if (!info->nmachines)
-        return 0;
-
-    if (!info->emulator || !STREQ(emulator, info->emulator))
-        return 0;
-
-    if (emulator_mtime != info->emulator_mtime) {
-        VIR_DEBUG("mtime on %s has changed, refreshing machine types",
-                  info->emulator);
-        return 0;
-    }
-
-    if (VIR_ALLOC_N(list, info->nmachines) < 0) {
-        virReportOOMError();
-        return 0;
-    }
-
-    for (i = 0; i < info->nmachines; i++) {
-        if (VIR_ALLOC(list[i]) < 0) {
-            goto no_memory;
-        }
-        if (info->machines[i]->name &&
-            !(list[i]->name = strdup(info->machines[i]->name))) {
-            goto no_memory;
-        }
-        if (info->machines[i]->canonical &&
-            !(list[i]->canonical = strdup(info->machines[i]->canonical))) {
-            goto no_memory;
-        }
-    }
-
-    *machines = list;
-    *nmachines = info->nmachines;
-
-    return 1;
-
-  no_memory:
-    virReportOOMError();
-    virCapabilitiesFreeMachines(list, info->nmachines);
-    return 0;
-}
-
-static int
-qemuCapsGetOldMachines(const char *ostype,
-                       const char *arch,
-                       int wordsize,
-                       const char *emulator,
-                       time_t emulator_mtime,
-                       virCapsPtr old_caps,
-                       virCapsGuestMachinePtr **machines,
-                       size_t *nmachines)
-{
-    int i;
-
-    for (i = 0; i < old_caps->nguests; i++) {
-        virCapsGuestPtr guest = old_caps->guests[i];
-        int j;
-
-        if (!STREQ(ostype, guest->ostype) ||
-            !STREQ(arch, guest->arch.name) ||
-            wordsize != guest->arch.wordsize)
-            continue;
-
-        for (j = 0; j < guest->arch.ndomains; j++) {
-            virCapsGuestDomainPtr dom = guest->arch.domains[j];
-
-            if (qemuCapsGetOldMachinesFromInfo(&dom->info,
-                                               emulator, emulator_mtime,
-                                               machines, nmachines))
-                return 1;
-        }
-
-        if (qemuCapsGetOldMachinesFromInfo(&guest->arch.defaultInfo,
-                                           emulator, emulator_mtime,
-                                           machines, nmachines))
-            return 1;
-    }
-
-    return 0;
-}
-
 
 typedef int
 (*qemuCapsParseCPUModels)(const char *output,
@@ -705,7 +614,7 @@ cleanup:
 
 static int
 qemuCapsInitGuest(virCapsPtr caps,
-                  virCapsPtr old_caps,
+                  qemuCapsCachePtr cache,
                   const char *hostmachine,
                   const struct qemu_arch_info *info,
                   int hvm)
@@ -716,11 +625,8 @@ qemuCapsInitGuest(virCapsPtr caps,
     int haskqemu = 0;
     char *kvmbin = NULL;
     char *binary = NULL;
-    time_t binary_mtime;
     virCapsGuestMachinePtr *machines = NULL;
     size_t nmachines = 0;
-    struct stat st;
-    size_t ncpus;
     qemuCapsPtr qemubinCaps = NULL;
     qemuCapsPtr kvmbinCaps = NULL;
     int ret = -1;
@@ -736,10 +642,12 @@ qemuCapsInitGuest(virCapsPtr caps,
     }
 
     /* Ignore binary if extracting version info fails */
-    if (binary &&
-        qemuCapsExtractVersionInfo(binary, info->arch,
-                                   false, NULL, &qemubinCaps) < 0)
-        VIR_FREE(binary);
+    if (binary) {
+        if (!(qemubinCaps = qemuCapsCacheLookup(cache, binary))) {
+            virResetLastError();
+            VIR_FREE(binary);
+        }
+    }
 
     /* qemu-kvm/kvm binaries can only be used if
      *  - host & guest arches match
@@ -759,9 +667,8 @@ qemuCapsInitGuest(virCapsPtr caps,
             if (!kvmbin)
                 continue;
 
-            if (qemuCapsExtractVersionInfo(kvmbin, info->arch,
-                                           false, NULL,
-                                           &kvmbinCaps) < 0) {
+            if (!(kvmbinCaps = qemuCapsCacheLookup(cache, kvmbin))) {
+                virResetLastError();
                 VIR_FREE(kvmbin);
                 continue;
             }
@@ -789,15 +696,6 @@ qemuCapsInitGuest(virCapsPtr caps,
         qemuCapsGet(qemubinCaps, QEMU_CAPS_KQEMU))
         haskqemu = 1;
 
-    if (stat(binary, &st) == 0) {
-        binary_mtime = st.st_mtime;
-    } else {
-        char ebuf[1024];
-        VIR_WARN("Failed to stat %s, most peculiar : %s",
-                 binary, virStrerror(errno, ebuf, sizeof(ebuf)));
-        binary_mtime = 0;
-    }
-
     if (info->machine) {
         virCapsGuestMachinePtr machine;
 
@@ -820,14 +718,7 @@ qemuCapsInitGuest(virCapsPtr caps,
 
         machines[0] = machine;
     } else {
-        int probe = 1;
-        if (old_caps && binary_mtime)
-            probe = !qemuCapsGetOldMachines(hvm ? "hvm" : "xen", info->arch,
-                                            info->wordsize, binary, binary_mtime,
-                                            old_caps, &machines, &nmachines);
-        if (probe &&
-            qemuCapsProbeMachineTypes(binary, qemubinCaps,
-                                      &machines, &nmachines) < 0)
+        if (qemuCapsGetMachineTypesCaps(qemubinCaps, &nmachines, &machines) < 0)
             goto error;
     }
 
@@ -846,11 +737,8 @@ qemuCapsInitGuest(virCapsPtr caps,
     machines = NULL;
     nmachines = 0;
 
-    guest->arch.defaultInfo.emulator_mtime = binary_mtime;
-
     if (caps->host.cpu &&
-        qemuCapsProbeCPUModels(binary, NULL, info->arch, &ncpus, NULL) == 0 &&
-        ncpus > 0 &&
+        qemuCapsGetCPUDefinitions(qemubinCaps, NULL) > 0 &&
         !virCapabilitiesAddGuestFeature(guest, "cpuselection", 1, 0))
         goto error;
 
@@ -879,28 +767,9 @@ qemuCapsInitGuest(virCapsPtr caps,
         if (haskvm) {
             virCapsGuestDomainPtr dom;
 
-            if (kvmbin) {
-                int probe = 1;
-
-                if (stat(kvmbin, &st) == 0) {
-                    binary_mtime = st.st_mtime;
-                } else {
-                    char ebuf[1024];
-                    VIR_WARN("Failed to stat %s, most peculiar : %s",
-                             binary, virStrerror(errno, ebuf, sizeof(ebuf)));
-                    binary_mtime = 0;
-                }
-
-                if (old_caps && binary_mtime)
-                    probe = !qemuCapsGetOldMachines("hvm", info->arch,
-                                                    info->wordsize, kvmbin,
-                                                    binary_mtime, old_caps,
-                                                    &machines, &nmachines);
-                if (probe &&
-                    qemuCapsProbeMachineTypes(kvmbin, kvmbinCaps,
-                                              &machines, &nmachines) < 0)
-                    goto error;
-            }
+            if (kvmbin &&
+                qemuCapsGetMachineTypesCaps(kvmbinCaps, &nmachines, &machines) < 0)
+                goto error;
 
             if ((dom = virCapabilitiesAddGuestDomain(guest,
                                                      "kvm",
@@ -914,7 +783,6 @@ qemuCapsInitGuest(virCapsPtr caps,
             machines = NULL;
             nmachines = 0;
 
-            dom->info.emulator_mtime = binary_mtime;
         }
     } else {
         if (virCapabilitiesAddGuestDomain(guest,
@@ -958,7 +826,7 @@ error:
 
 static int
 qemuCapsInitCPU(virCapsPtr caps,
-                 const char *arch)
+                const char *arch)
 {
     virCPUDefPtr cpu = NULL;
     union cpuData *data = NULL;
@@ -1004,7 +872,7 @@ static int qemuDefaultConsoleType(const char *ostype ATTRIBUTE_UNUSED)
 }
 
 
-virCapsPtr qemuCapsInit(virCapsPtr old_caps)
+virCapsPtr qemuCapsInit(qemuCapsCachePtr cache)
 {
     struct utsname utsname;
     virCapsPtr caps;
@@ -1030,14 +898,8 @@ virCapsPtr qemuCapsInit(virCapsPtr old_caps)
         VIR_WARN("Failed to query host NUMA topology, disabling NUMA capabilities");
     }
 
-    if (old_caps == NULL || old_caps->host.cpu == NULL) {
-        if (qemuCapsInitCPU(caps, utsname.machine) < 0)
-            VIR_WARN("Failed to get host CPU");
-    }
-    else {
-        caps->host.cpu = old_caps->host.cpu;
-        old_caps->host.cpu = NULL;
-    }
+    if (qemuCapsInitCPU(caps, utsname.machine) < 0)
+        VIR_WARN("Failed to get host CPU");
 
     /* Add the power management features of the host */
 
@@ -1049,7 +911,7 @@ virCapsPtr qemuCapsInit(virCapsPtr old_caps)
 
     /* First the pure HVM guests */
     for (i = 0 ; i < ARRAY_CARDINALITY(arch_info_hvm) ; i++)
-        if (qemuCapsInitGuest(caps, old_caps,
+        if (qemuCapsInitGuest(caps, cache,
                               utsname.machine,
                               &arch_info_hvm[i], 1) < 0)
             goto no_memory;
@@ -1064,7 +926,7 @@ virCapsPtr qemuCapsInit(virCapsPtr old_caps)
             if (STREQ(arch_info_xen[i].arch, utsname.machine) ||
                 (STREQ(utsname.machine, "x86_64") &&
                  STREQ(arch_info_xen[i].arch, "i686"))) {
-                if (qemuCapsInitGuest(caps, old_caps,
+                if (qemuCapsInitGuest(caps, cache,
                                       utsname.machine,
                                       &arch_info_xen[i], 0) < 0)
                     goto no_memory;
@@ -1873,6 +1735,11 @@ qemuCapsGet(qemuCapsPtr caps,
 }
 
 
+const char *qemuCapsGetBinary(qemuCapsPtr caps)
+{
+    return caps->binary;
+}
+
 const char *qemuCapsGetArch(qemuCapsPtr caps)
 {
     return caps->arch;
@@ -1894,7 +1761,8 @@ unsigned int qemuCapsGetKVMVersion(qemuCapsPtr caps)
 size_t qemuCapsGetCPUDefinitions(qemuCapsPtr caps,
                                  char ***names)
 {
-    *names = caps->cpuDefinitions;
+    if (names)
+        *names = caps->cpuDefinitions;
     return caps->ncpuDefinitions;
 }
 
@@ -1902,10 +1770,50 @@ size_t qemuCapsGetCPUDefinitions(qemuCapsPtr caps,
 size_t qemuCapsGetMachineTypes(qemuCapsPtr caps,
                                char ***names)
 {
-    *names = caps->machineTypes;
+    if (names)
+        *names = caps->machineTypes;
     return caps->nmachineTypes;
 }
 
+int qemuCapsGetMachineTypesCaps(qemuCapsPtr caps,
+                                size_t *nmachines,
+                                virCapsGuestMachinePtr **machines)
+{
+    size_t i;
+
+    *nmachines = 0;
+    *machines = NULL;
+    if (VIR_ALLOC_N(*machines, caps->nmachineTypes) < 0)
+        goto no_memory;
+    *nmachines = caps->nmachineTypes;
+
+    for (i = 0 ; i < caps->nmachineTypes ; i++) {
+        virCapsGuestMachinePtr mach;
+        if (VIR_ALLOC(mach) < 0)
+            goto no_memory;
+        if (caps->machineAliases[i]) {
+            if (!(mach->name = strdup(caps->machineAliases[i])))
+                goto no_memory;
+            if (!(mach->canonical = strdup(caps->machineTypes[i])))
+                goto no_memory;
+        } else {
+            if (!(mach->name = strdup(caps->machineTypes[i])))
+                goto no_memory;
+        }
+        (*machines)[i] = mach;
+    }
+
+    return 0;
+
+no_memory:
+    virCapabilitiesFreeMachines(*machines, *nmachines);
+    *nmachines = 0;
+    *machines = NULL;
+    return -1;
+}
+
+
+
 
 const char *qemuCapsGetCanonicalMachine(qemuCapsPtr caps,
                                         const char *name)
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 27ed378..942740d 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -174,6 +174,7 @@ bool qemuCapsGet(qemuCapsPtr caps,
 
 char *qemuCapsFlagsString(qemuCapsPtr caps);
 
+const char *qemuCapsGetBinary(qemuCapsPtr caps);
 const char *qemuCapsGetArch(qemuCapsPtr caps);
 unsigned int qemuCapsGetVersion(qemuCapsPtr caps);
 unsigned int qemuCapsGetKVMVersion(qemuCapsPtr caps);
@@ -184,6 +185,10 @@ size_t qemuCapsGetMachineTypes(qemuCapsPtr caps,
 const char *qemuCapsGetCanonicalMachine(qemuCapsPtr caps,
                                         const char *name);
 
+int qemuCapsGetMachineTypesCaps(qemuCapsPtr caps,
+                                size_t *nmachines,
+                                virCapsGuestMachinePtr **machines);
+
 bool qemuCapsIsValid(qemuCapsPtr caps);
 
 
@@ -192,7 +197,7 @@ qemuCapsPtr qemuCapsCacheLookup(qemuCapsCachePtr cache, const char *binary);
 qemuCapsPtr qemuCapsCacheLookupCopy(qemuCapsCachePtr cache, const char *binary);
 void qemuCapsCacheFree(qemuCapsCachePtr cache);
 
-virCapsPtr qemuCapsInit(virCapsPtr old_caps);
+virCapsPtr qemuCapsInit(qemuCapsCachePtr cache);
 
 int qemuCapsProbeMachineTypes(const char *binary,
                               qemuCapsPtr caps,
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 180c144..ca2f694 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -43,6 +43,7 @@
 # include "command.h"
 # include "threadpool.h"
 # include "locking/lock_manager.h"
+# include "qemu_capabilities.h"
 
 # define QEMUD_CPUMASK_LEN CPU_SETSIZE
 
@@ -115,6 +116,7 @@ struct qemud_driver {
     int max_queued;
 
     virCapsPtr caps;
+    qemuCapsCachePtr capsCache;
 
     virDomainEventStatePtr domainEventState;
 
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 226d499..e0c5cdb 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -378,8 +378,7 @@ error:
 
 
 static virCapsPtr
-qemuCreateCapabilities(virCapsPtr oldcaps,
-                       struct qemud_driver *driver)
+qemuCreateCapabilities(struct qemud_driver *driver)
 {
     size_t i;
     virCapsPtr caps;
@@ -388,7 +387,7 @@ qemuCreateCapabilities(virCapsPtr oldcaps,
     const char *doi, *model;
 
     /* Basic host arch / guest machine capabilities */
-    if (!(caps = qemuCapsInit(oldcaps))) {
+    if (!(caps = qemuCapsInit(driver->capsCache))) {
         virReportOOMError();
         return NULL;
     }
@@ -768,8 +767,10 @@ qemudStartup(int privileged) {
     if (qemuSecurityInit(qemu_driver) < 0)
         goto error;
 
-    if ((qemu_driver->caps = qemuCreateCapabilities(NULL,
-                                                    qemu_driver)) == NULL)
+    if ((qemu_driver->capsCache = qemuCapsCacheNew()) == NULL)
+        goto error;
+
+    if ((qemu_driver->caps = qemuCreateCapabilities(qemu_driver)) == NULL)
         goto error;
 
     if ((qemu_driver->activePciHostdevs = pciDeviceListNew()) == NULL)
@@ -985,6 +986,7 @@ qemudShutdown(void) {
     pciDeviceListFree(qemu_driver->inactivePciHostdevs);
     usbDeviceListFree(qemu_driver->activeUsbHostdevs);
     virCapabilitiesFree(qemu_driver->caps);
+    qemuCapsCacheFree(qemu_driver->capsCache);
 
     virDomainObjListDeinit(&qemu_driver->domains);
     virBitmapFree(qemu_driver->reservedRemotePorts);
@@ -1224,8 +1226,7 @@ static char *qemudGetCapabilities(virConnectPtr conn) {
 
     qemuDriverLock(driver);
 
-    if ((caps = qemuCreateCapabilities(qemu_driver->caps,
-                                       qemu_driver)) == NULL) {
+    if ((caps = qemuCreateCapabilities(qemu_driver)) == NULL) {
         virCapabilitiesFree(caps);
         goto cleanup;
     }
-- 
1.7.11.4




More information about the libvir-list mailing list