---
src/qemu/qemu_capabilities.c | 11 +++++++
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_conf.c | 59 +++++++++++++++++++++++++++++++-----
3 files changed, 64 insertions(+), 7 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 46ba5e30b5..a3c1348157 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -582,6 +582,7 @@ struct _virQEMUCaps {
virArch arch;
+ virHashTablePtr domCapsCache;
virDomainCapsCPUModelsPtr kvmCPUModels;
virDomainCapsCPUModelsPtr tcgCPUModels;
@@ -1476,6 +1477,9 @@ virQEMUCapsNew(void)
if (!(qemuCaps->flags = virBitmapNew(QEMU_CAPS_LAST)))
goto error;
+ if (!(qemuCaps->domCapsCache = virHashCreate(5, virObjectFreeHashData)))
+ goto error;
+
return qemuCaps;
error:
@@ -1628,6 +1632,7 @@ void virQEMUCapsDispose(void *obj)
}
VIR_FREE(qemuCaps->machineTypes);
+ virHashFree(qemuCaps->domCapsCache);
virObjectUnref(qemuCaps->kvmCPUModels);
virObjectUnref(qemuCaps->tcgCPUModels);
@@ -1790,6 +1795,12 @@ const char *virQEMUCapsGetPackage(virQEMUCapsPtr qemuCaps)
}
+virHashTablePtr virQEMUCapsGetDomainCapsCache(virQEMUCapsPtr qemuCaps)
+{
+ return qemuCaps->domCapsCache;
+}
+
+
int
virQEMUCapsAddCPUDefinitions(virQEMUCapsPtr qemuCaps,
virDomainVirtType type,
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index c6f6980684..2a37f0c2ff 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -538,6 +538,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,
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 635fdcc5a4..6a7c183075 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1358,10 +1358,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
*/
@@ -1375,18 +1404,34 @@ 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,
- cfg->firmwares, cfg->nfirmwares) < 0)
- goto cleanup;
+ if (virQEMUCapsFillDomainCaps(caps, domCaps, qemuCaps,
+ 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);