]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: conf: Cache domCaps in qemuCaps
authorCole Robinson <crobinso@redhat.com>
Thu, 4 Apr 2019 21:06:12 +0000 (17:06 -0400)
committerCole Robinson <crobinso@redhat.com>
Tue, 6 Aug 2019 23:45:49 +0000 (19:45 -0400)
qemuCaps is tied to a binary on disk. domCaps is tied to a combo
of binary+machine+arch+virttype values. For the qemu driver this almost
entirely translates to a permutation of qemuCaps though

Upcoming patches want to use the domCaps data store at XML validate
time, but we need to cache the data so we aren't repeatedly
regenerating it.

Add a domCapsCache hash table to qemuCaps. This ensures that the domCaps
cache is blown away whenever qemuCaps needs to be regenerated. Similarly
when qemuCaps is invalidated, the next call to virQEMUCapsCacheLookup
will unref qemuCaps and free our cache as well.

Adjust virQEMUDriverGetDomainCapabilities to search the cache and add
to it if we don't find a hit.

Signed-off-by: Cole Robinson <crobinso@redhat.com>
Reviewed-by: Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
src/qemu/qemu_capabilities.c
src/qemu/qemu_capabilities.h
src/qemu/qemu_conf.c

index 2c46a15b0f30f80846348b80ed49bdc21d883add..405bc3f288431fe30b15bbb1014efe38b2445539 100644 (file)
@@ -595,6 +595,7 @@ struct _virQEMUCaps {
 
     virArch arch;
 
+    virHashTablePtr domCapsCache;
     virDomainCapsCPUModelsPtr kvmCPUModels;
     virDomainCapsCPUModelsPtr tcgCPUModels;
 
@@ -1509,6 +1510,9 @@ virQEMUCapsNew(void)
     if (!(qemuCaps->flags = virBitmapNew(QEMU_CAPS_LAST)))
         goto error;
 
+    if (!(qemuCaps->domCapsCache = virHashCreate(5, virObjectFreeHashData)))
+        goto error;
+
     return qemuCaps;
 
  error:
@@ -1661,6 +1665,7 @@ void virQEMUCapsDispose(void *obj)
     }
     VIR_FREE(qemuCaps->machineTypes);
 
+    virHashFree(qemuCaps->domCapsCache);
     virObjectUnref(qemuCaps->kvmCPUModels);
     virObjectUnref(qemuCaps->tcgCPUModels);
 
@@ -1823,6 +1828,12 @@ const char *virQEMUCapsGetPackage(virQEMUCapsPtr qemuCaps)
 }
 
 
+virHashTablePtr virQEMUCapsGetDomainCapsCache(virQEMUCapsPtr qemuCaps)
+{
+    return qemuCaps->domCapsCache;
+}
+
+
 int
 virQEMUCapsAddCPUDefinitions(virQEMUCapsPtr qemuCaps,
                              virDomainVirtType type,
index 3cb56e63f4916f53bb097ea4467e41cca7793499..d7c6df20c7e4500956afc7be4546e698a1cdc8f7 100644 (file)
@@ -549,6 +549,7 @@ const char *virQEMUCapsGetBinary(virQEMUCapsPtr qemuCaps);
 virArch virQEMUCapsGetArch(virQEMUCapsPtr qemuCaps);
 unsigned int virQEMUCapsGetVersion(virQEMUCapsPtr qemuCaps);
 const char *virQEMUCapsGetPackage(virQEMUCapsPtr qemuCaps);
+virHashTablePtr virQEMUCapsGetDomainCapsCache(virQEMUCapsPtr qemuCaps);
 unsigned int virQEMUCapsGetKVMVersion(virQEMUCapsPtr qemuCaps);
 int virQEMUCapsAddCPUDefinitions(virQEMUCapsPtr qemuCaps,
                                  virDomainVirtType type,
index b6aadf358794c12beed26e5ce0049a0c8262d540..295389333770d0a55d81b118197282056acef779 100644 (file)
@@ -1364,10 +1364,39 @@ virCapsPtr virQEMUDriverGetCapabilities(virQEMUDriverPtr driver,
 }
 
 
+struct virQEMUDriverSearchDomcapsData {
+    const char *path;
+    const char *machine;
+    virArch arch;
+    virDomainVirtType virttype;
+};
+
+
+static int
+virQEMUDriverSearchDomcaps(const void *payload,
+                           const void *name ATTRIBUTE_UNUSED,
+                           const void *opaque)
+{
+    virDomainCapsPtr domCaps = (virDomainCapsPtr) payload;
+    struct virQEMUDriverSearchDomcapsData *data = (struct virQEMUDriverSearchDomcapsData *) opaque;
+
+    if (STREQ_NULLABLE(data->path, domCaps->path) &&
+        STREQ_NULLABLE(data->machine, domCaps->machine) &&
+        data->arch == domCaps->arch &&
+        data->virttype == domCaps->virttype)
+        return 1;
+
+    return 0;
+}
+
 /**
  * virQEMUDriverGetDomainCapabilities:
  *
- * Build a virDomainCapsPtr instance for the passed data.
+ * Get a reference to the virDomainCapsPtr instance from the virQEMUCapsPtr
+ * domCapsCache. If there's no domcaps in the cache, create a new instance,
+ * add it to the cache, and return a reference.
+ *
+ * The caller must release the reference with virObjetUnref
  *
  * Returns: a reference to a virDomainCapsPtr instance or NULL
  */
@@ -1381,18 +1410,35 @@ virQEMUDriverGetDomainCapabilities(virQEMUDriverPtr driver,
     virDomainCapsPtr ret = NULL, domCaps = NULL;
     virCapsPtr caps = NULL;
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+    virHashTablePtr domCapsCache = virQEMUCapsGetDomainCapsCache(qemuCaps);
+    struct virQEMUDriverSearchDomcapsData data = {
+        .path = virQEMUCapsGetBinary(qemuCaps),
+        .machine = machine,
+        .arch = arch,
+        .virttype = virttype,
+    };
 
     if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
         goto cleanup;
 
-    if (!(domCaps = virDomainCapsNew(virQEMUCapsGetBinary(qemuCaps), machine,
-                                     arch, virttype)))
-        goto cleanup;
+    domCaps = virHashSearch(domCapsCache,
+                            virQEMUDriverSearchDomcaps, &data, NULL);
+    if (!domCaps) {
+        /* hash miss, build new domcaps */
+        if (!(domCaps = virDomainCapsNew(data.path, data.machine,
+                                         data.arch, data.virttype)))
+            goto cleanup;
 
-    if (virQEMUCapsFillDomainCaps(caps, domCaps, qemuCaps, driver->privileged,
-                                  cfg->firmwares, cfg->nfirmwares) < 0)
-        goto cleanup;
+        if (virQEMUCapsFillDomainCaps(caps, domCaps, qemuCaps,
+                                      driver->privileged,
+                                      cfg->firmwares, cfg->nfirmwares) < 0)
+            goto cleanup;
+
+        if (virHashAddEntry(domCapsCache, machine, domCaps) < 0)
+            goto cleanup;
+    }
 
+    virObjectRef(domCaps);
     VIR_STEAL_PTR(ret, domCaps);
  cleanup:
     virObjectUnref(domCaps);