[libvirt] [PATCH 28/30] qemu: use host CPU object directly

Daniel P. Berrangé berrange at redhat.com
Wed Dec 4 14:21:11 UTC 2019


Avoid grabbing the whole virCapsPtr object when we only need the
host CPU information.

Signed-off-by: Daniel P. Berrangé <berrange at redhat.com>
---
 src/qemu/qemu_capabilities.c |  3 --
 src/qemu/qemu_conf.c         | 17 +++++++++
 src/qemu/qemu_conf.h         |  6 ++++
 src/qemu/qemu_driver.c       |  6 ++--
 src/qemu/qemu_process.c      | 68 +++++++++++++++---------------------
 tests/domaincapstest.c       | 14 +++-----
 tests/qemucapabilitiestest.c |  9 ++---
 tests/qemuxml2argvtest.c     |  8 ++---
 tests/testutilsqemu.c        | 49 +++++++++++---------------
 tests/testutilsqemu.h        |  5 ++-
 10 files changed, 89 insertions(+), 96 deletions(-)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 16c4331b13..1b395a2570 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -1035,9 +1035,6 @@ virQEMUCapsInit(virFileCachePtr cache)
     if (virCapabilitiesInitCaches(caps) < 0)
         VIR_WARN("Failed to get host CPU cache info");
 
-    if (!(caps->host.cpu = virCPUProbeHost(caps->host.arch)))
-        VIR_WARN("Failed to get host CPU");
-
     /* Add the power management features of the host */
     if (virNodeSuspendGetTargetMask(&caps->host.powerMgmt) < 0)
         VIR_WARN("Failed to get host power management capabilities");
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index ba3001ccd0..9df4ae1230 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1220,6 +1220,22 @@ virQEMUDriverGetHostNUMACaps(virQEMUDriverPtr driver)
 }
 
 
+virCPUDefPtr
+virQEMUDriverGetHostCPU(virQEMUDriverPtr driver)
+{
+    qemuDriverLock(driver);
+
+    if (!driver->hostcpu)
+        driver->hostcpu = virCPUProbeHost(virArchFromHost());
+
+    qemuDriverUnlock(driver);
+
+    virCPUDefRef(driver->hostcpu);
+
+    return driver->hostcpu;
+}
+
+
 virCapsPtr virQEMUDriverCreateCapabilities(virQEMUDriverPtr driver)
 {
     size_t i, j;
@@ -1272,6 +1288,7 @@ virCapsPtr virQEMUDriverCreateCapabilities(virQEMUDriverPtr driver)
     }
 
     caps->host.numa = virQEMUDriverGetHostNUMACaps(driver);
+    caps->host.cpu = virQEMUDriverGetHostCPU(driver);
     return g_steal_pointer(&caps);
 }
 
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 2d03df9171..d2e0bd97e1 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -267,6 +267,11 @@ struct _virQEMUDriver {
      */
     virCapsHostNUMAPtr hostnuma;
 
+    /* Lazy initialized on first use, immutable thereafter.
+     * Require lock to get the pointer & do optional initialization
+     */
+    virCPUDefPtr hostcpu;
+
     /* Immutable value */
     virArch hostarch;
 
@@ -325,6 +330,7 @@ virQEMUDriverConfigPtr virQEMUDriverGetConfig(virQEMUDriverPtr driver);
 bool virQEMUDriverIsPrivileged(virQEMUDriverPtr driver);
 
 virCapsHostNUMAPtr virQEMUDriverGetHostNUMACaps(virQEMUDriverPtr driver);
+virCPUDefPtr virQEMUDriverGetHostCPU(virQEMUDriverPtr driver);
 virCapsPtr virQEMUDriverCreateCapabilities(virQEMUDriverPtr driver);
 virCapsPtr virQEMUDriverGetCapabilities(virQEMUDriverPtr driver,
                                         bool refresh);
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index ae6facc829..1fe310e16c 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -13354,7 +13354,7 @@ qemuConnectCompareCPU(virConnectPtr conn,
                       unsigned int flags)
 {
     virQEMUDriverPtr driver = conn->privateData;
-    g_autoptr(virCaps) caps = NULL;
+    g_autoptr(virCPUDef) cpu = NULL;
     bool failIncompatible;
 
     virCheckFlags(VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE,
@@ -13365,10 +13365,10 @@ qemuConnectCompareCPU(virConnectPtr conn,
 
     failIncompatible = !!(flags & VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE);
 
-    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
+    if (!(cpu = virQEMUDriverGetHostCPU(driver)))
         return VIR_CPU_COMPARE_ERROR;
 
-    return virCPUCompareXML(driver->hostarch, caps->host.cpu,
+    return virCPUCompareXML(driver->hostarch, cpu,
                             xmlDesc, failIncompatible);
 }
 
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index cc89ff8571..3a3860b1a3 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5291,12 +5291,13 @@ qemuProcessStartValidateDisks(virDomainObjPtr vm,
 
 
 static int
-qemuProcessStartValidateTSC(virDomainObjPtr vm,
-                            virCapsPtr caps)
+qemuProcessStartValidateTSC(virQEMUDriverPtr driver,
+                            virDomainObjPtr vm)
 {
     size_t i;
     unsigned long long freq = 0;
     virHostCPUTscInfoPtr tsc;
+    g_autoptr(virCPUDef) cpu = NULL;
 
     for (i = 0; i < vm->def->clock.ntimers; i++) {
         virDomainTimerDefPtr timer = vm->def->clock.timers[i];
@@ -5313,12 +5314,13 @@ qemuProcessStartValidateTSC(virDomainObjPtr vm,
 
     VIR_DEBUG("Requested TSC frequency %llu Hz", freq);
 
-    if (!caps->host.cpu || !caps->host.cpu->tsc) {
+    cpu = virQEMUDriverGetHostCPU(driver);
+    if (!cpu || !cpu->tsc) {
         VIR_DEBUG("Host TSC frequency could not be probed");
         return 0;
     }
 
-    tsc = caps->host.cpu->tsc;
+    tsc = cpu->tsc;
     VIR_DEBUG("Host TSC frequency %llu Hz, scaling %s",
               tsc->frequency, virTristateBoolTypeToString(tsc->scaling));
 
@@ -5356,7 +5358,6 @@ static int
 qemuProcessStartValidate(virQEMUDriverPtr driver,
                          virDomainObjPtr vm,
                          virQEMUCapsPtr qemuCaps,
-                         virCapsPtr caps,
                          unsigned int flags)
 {
     if (!(flags & VIR_QEMU_PROCESS_START_PRETEND)) {
@@ -5424,7 +5425,7 @@ qemuProcessStartValidate(virQEMUDriverPtr driver,
     if (qemuProcessStartValidateDisks(vm, qemuCaps) < 0)
         return -1;
 
-    if (qemuProcessStartValidateTSC(vm, caps) < 0)
+    if (qemuProcessStartValidateTSC(driver, vm) < 0)
         return -1;
 
     VIR_DEBUG("Checking for any possible (non-fatal) issues");
@@ -5555,7 +5556,6 @@ qemuProcessInit(virQEMUDriverPtr driver,
                 bool migration,
                 unsigned int flags)
 {
-    virCapsPtr caps = NULL;
     qemuDomainObjPrivatePtr priv = vm->privateData;
     int stopFlags;
     virCPUDefPtr origCPU = NULL;
@@ -5572,9 +5572,6 @@ qemuProcessInit(virQEMUDriverPtr driver,
         goto cleanup;
     }
 
-    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
-        goto cleanup;
-
     /* in case when the post parse callback failed we need to re-run it on the
      * old config prior we start the VM */
     if (vm->def->postParseFailed) {
@@ -5592,7 +5589,7 @@ qemuProcessInit(virQEMUDriverPtr driver,
     if (qemuDomainUpdateCPU(vm, updatedCPU, &origCPU) < 0)
         goto cleanup;
 
-    if (qemuProcessStartValidate(driver, vm, priv->qemuCaps, caps, flags) < 0)
+    if (qemuProcessStartValidate(driver, vm, priv->qemuCaps, flags) < 0)
         goto cleanup;
 
     /* Do this upfront, so any part of the startup process can add
@@ -5632,7 +5629,6 @@ qemuProcessInit(virQEMUDriverPtr driver,
 
  cleanup:
     virCPUDefFree(origCPU);
-    virObjectUnref(caps);
     return ret;
 
  stop:
@@ -7803,20 +7799,20 @@ static int
 qemuProcessRefreshCPU(virQEMUDriverPtr driver,
                       virDomainObjPtr vm)
 {
-    virCapsPtr caps = virQEMUDriverGetCapabilities(driver, false);
     qemuDomainObjPrivatePtr priv = vm->privateData;
-    virCPUDefPtr host = NULL;
-    virCPUDefPtr cpu = NULL;
-    int ret = -1;
+    g_autoptr(virCPUDef) host = NULL;
+    g_autoptr(virCPUDef) hostmig = NULL;
+    g_autoptr(virCPUDef) cpu = NULL;
 
-    if (!caps)
-        return -1;
+    if (!virQEMUCapsGuestIsNative(driver->hostarch, vm->def->os.arch))
+        return 0;
 
-    if (!virQEMUCapsGuestIsNative(driver->hostarch, vm->def->os.arch) ||
-        !caps->host.cpu ||
-        !vm->def->cpu) {
-        ret = 0;
-        goto cleanup;
+    if (!vm->def->cpu)
+        return 0;
+
+    if (!(host = virQEMUDriverGetHostCPU(driver))) {
+        virResetLastError();
+        return 0;
     }
 
     /* If the domain with a host-model CPU was started by an old libvirt
@@ -7825,20 +7821,20 @@ qemuProcessRefreshCPU(virQEMUDriverPtr driver,
      * running domain.
      */
     if (vm->def->cpu->mode == VIR_CPU_MODE_HOST_MODEL) {
-        if (!(host = virCPUCopyMigratable(caps->host.cpu->arch, caps->host.cpu)))
-            goto cleanup;
+        if (!(hostmig = virCPUCopyMigratable(host->arch, host)))
+            return -1;
 
-        if (!(cpu = virCPUDefCopyWithoutModel(host)) ||
-            virCPUDefCopyModelFilter(cpu, host, false,
+        if (!(cpu = virCPUDefCopyWithoutModel(hostmig)) ||
+            virCPUDefCopyModelFilter(cpu, hostmig, false,
                                      virQEMUCapsCPUFilterFeatures,
-                                     &caps->host.cpu->arch) < 0)
-            goto cleanup;
+                                     &host->arch) < 0)
+            return -1;
 
         if (virCPUUpdate(vm->def->os.arch, vm->def->cpu, cpu) < 0)
-            goto cleanup;
+            return -1;
 
         if (qemuProcessUpdateCPU(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
-            goto cleanup;
+            return -1;
     } else if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION)) {
         /* We only try to fix CPUs when the libvirt/QEMU combo used to start
          * the domain did not know about query-cpu-model-expansion in which
@@ -7846,16 +7842,10 @@ qemuProcessRefreshCPU(virQEMUDriverPtr driver,
          * doesn't know about.
          */
         if (qemuDomainFixupCPUs(vm, &priv->origCPU) < 0)
-            goto cleanup;
+            return -1;
     }
 
-    ret = 0;
-
- cleanup:
-    virCPUDefFree(cpu);
-    virCPUDefFree(host);
-    virObjectUnref(caps);
-    return ret;
+    return 0;
 }
 
 
diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c
index 94e5831706..a4a443b1d6 100644
--- a/tests/domaincapstest.c
+++ b/tests/domaincapstest.c
@@ -54,8 +54,7 @@ fillStringValues(virDomainCapsStringValuesPtr values, ...)
 # include "testutilshostcpus.h"
 
 static int
-fakeHostCPU(virCapsPtr caps,
-            virArch arch)
+fakeHostCPU(virArch arch)
 {
     virCPUDefPtr cpu;
 
@@ -66,7 +65,7 @@ fakeHostCPU(virCapsPtr caps,
         return -1;
     }
 
-    qemuTestSetHostCPU(caps, cpu);
+    qemuTestSetHostCPU(NULL, arch, cpu);
 
     return 0;
 }
@@ -80,17 +79,15 @@ fillQemuCaps(virDomainCapsPtr domCaps,
 {
     int ret = -1;
     char *path = NULL;
-    virCapsPtr caps = NULL;
     virQEMUCapsPtr qemuCaps = NULL;
     virDomainCapsLoaderPtr loader = &domCaps->os.loader;
     virDomainVirtType virtType;
 
-    if (!(caps = virCapabilitiesNew(domCaps->arch, false, false)) ||
-        fakeHostCPU(caps, domCaps->arch) < 0)
+    if (fakeHostCPU(domCaps->arch) < 0)
         goto cleanup;
 
     path = g_strdup_printf("%s/%s.%s.xml", TEST_QEMU_CAPS_PATH, name, arch);
-    if (!(qemuCaps = qemuTestParseCapabilities(caps, path)))
+    if (!(qemuCaps = qemuTestParseCapabilitiesArch(domCaps->arch, path)))
         goto cleanup;
 
     if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM))
@@ -106,7 +103,7 @@ fillQemuCaps(virDomainCapsPtr domCaps,
     if (!domCaps->machine)
         domCaps->machine = g_strdup(virQEMUCapsGetPreferredMachine(qemuCaps, virtType));
 
-    if (virQEMUCapsFillDomainCaps(qemuCaps, caps->host.arch, domCaps,
+    if (virQEMUCapsFillDomainCaps(qemuCaps, domCaps->arch, domCaps,
                                   false,
                                   cfg->firmwares,
                                   cfg->nfirmwares) < 0)
@@ -134,7 +131,6 @@ fillQemuCaps(virDomainCapsPtr domCaps,
 
     ret = 0;
  cleanup:
-    virObjectUnref(caps);
     virObjectUnref(qemuCaps);
     VIR_FREE(path);
     return ret;
diff --git a/tests/qemucapabilitiestest.c b/tests/qemucapabilitiestest.c
index 3d3e6b6d57..b38c0f6f65 100644
--- a/tests/qemucapabilitiestest.c
+++ b/tests/qemucapabilitiestest.c
@@ -144,7 +144,6 @@ testQemuCapsCopy(const void *opaque)
     int ret = -1;
     const testQemuData *data = opaque;
     char *capsFile = NULL;
-    virCapsPtr caps = NULL;
     virQEMUCapsPtr orig = NULL;
     virQEMUCapsPtr copy = NULL;
     char *actual = NULL;
@@ -153,11 +152,8 @@ testQemuCapsCopy(const void *opaque)
                                data->outputDir, data->prefix, data->version,
                                data->archName);
 
-    if (!(caps = virCapabilitiesNew(virArchFromString(data->archName),
-                                    false, false)))
-        goto cleanup;
-
-    if (!(orig = qemuTestParseCapabilities(caps, capsFile)))
+    if (!(orig = qemuTestParseCapabilitiesArch(
+              virArchFromString(data->archName), capsFile)))
         goto cleanup;
 
     if (!(copy = virQEMUCapsNewCopy(orig)))
@@ -173,7 +169,6 @@ testQemuCapsCopy(const void *opaque)
 
  cleanup:
     VIR_FREE(capsFile);
-    virObjectUnref(caps);
     virObjectUnref(orig);
     virObjectUnref(copy);
     VIR_FREE(actual);
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index fe8fa776be..ba4a92ec0a 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -1733,7 +1733,7 @@ mymain(void)
     DO_TEST_FAILURE("cpu-s390-features", QEMU_CAPS_KVM);
     qemuTestSetHostArch(&driver, VIR_ARCH_NONE);
 
-    qemuTestSetHostCPU(driver.caps, cpuHaswell);
+    qemuTestSetHostCPU(&driver, driver.hostarch, cpuHaswell);
     DO_TEST("cpu-Haswell", QEMU_CAPS_KVM);
     DO_TEST("cpu-Haswell2", QEMU_CAPS_KVM);
     DO_TEST("cpu-Haswell3", QEMU_CAPS_KVM);
@@ -1744,7 +1744,7 @@ mymain(void)
     DO_TEST_CAPS_VER("cpu-tsc-frequency", "4.0.0");
     DO_TEST_CAPS_VER("cpu-translation", "4.0.0");
     DO_TEST_CAPS_LATEST("cpu-translation");
-    qemuTestSetHostCPU(driver.caps, NULL);
+    qemuTestSetHostCPU(&driver, driver.hostarch, NULL);
 
     DO_TEST("encrypted-disk", QEMU_CAPS_QCOW2_LUKS, QEMU_CAPS_OBJECT_SECRET);
     DO_TEST("encrypted-disk-usage", QEMU_CAPS_QCOW2_LUKS, QEMU_CAPS_OBJECT_SECRET);
@@ -1873,12 +1873,12 @@ mymain(void)
                     QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE,
                     QEMU_CAPS_KVM);
 
-    qemuTestSetHostCPU(driver.caps, cpuPower9);
+    qemuTestSetHostCPU(&driver, driver.hostarch, cpuPower9);
     DO_TEST("pseries-cpu-compat-power9",
             QEMU_CAPS_KVM,
             QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE,
             QEMU_CAPS_DEVICE_SPAPR_VTY);
-    qemuTestSetHostCPU(driver.caps, NULL);
+    qemuTestSetHostCPU(&driver, driver.hostarch, NULL);
 
     qemuTestSetHostArch(&driver, VIR_ARCH_NONE);
 
diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c
index fb9b85747a..6fd121855d 100644
--- a/tests/testutilsqemu.c
+++ b/tests/testutilsqemu.c
@@ -205,14 +205,6 @@ virCapsPtr testQemuCapsInit(void)
     caps->host.secModels[0].model = g_strdup("none");
     caps->host.secModels[0].doi = g_strdup("0");
 
-    if (!(cpuDefault = virCPUDefCopy(&cpuDefaultData)) ||
-        !(cpuHaswell = virCPUDefCopy(&cpuHaswellData)) ||
-        !(cpuPower8 = virCPUDefCopy(&cpuPower8Data)) ||
-        !(cpuPower9 = virCPUDefCopy(&cpuPower9Data)))
-        goto cleanup;
-
-    qemuTestSetHostCPU(caps, NULL);
-
     if (!(caps->host.numa = virCapabilitiesHostNUMANewHost()))
         goto cleanup;
 
@@ -237,9 +229,6 @@ virCapsPtr testQemuCapsInit(void)
 
  cleanup:
     caps->host.cpu = NULL;
-    virCPUDefFree(cpuDefault);
-    virCPUDefFree(cpuHaswell);
-    virCPUDefFree(cpuPower8);
     virObjectUnref(caps);
     return NULL;
 }
@@ -255,16 +244,15 @@ qemuTestSetHostArch(virQEMUDriverPtr driver,
     virTestHostArch = arch;
     driver->hostarch = virArchFromHost();
     driver->caps->host.arch = virArchFromHost();
-    qemuTestSetHostCPU(driver->caps, NULL);
+    qemuTestSetHostCPU(driver, arch, NULL);
 }
 
 
 void
-qemuTestSetHostCPU(virCapsPtr caps,
+qemuTestSetHostCPU(virQEMUDriverPtr driver,
+                   virArch arch,
                    virCPUDefPtr cpu)
 {
-    virArch arch = caps->host.arch;
-
     if (!cpu) {
         if (ARCH_IS_X86(arch))
             cpu = cpuDefault;
@@ -274,11 +262,19 @@ qemuTestSetHostCPU(virCapsPtr caps,
 
     unsetenv("VIR_TEST_MOCK_FAKE_HOST_CPU");
     if (cpu) {
-        caps->host.arch = cpu->arch;
         if (cpu->model)
             setenv("VIR_TEST_MOCK_FAKE_HOST_CPU", cpu->model, 1);
     }
-    caps->host.cpu = cpu;
+    if (driver) {
+        if (cpu)
+            driver->caps->host.arch = cpu->arch;
+        driver->caps->host.cpu = cpu;
+
+        virCPUDefFree(driver->hostcpu);
+        if (cpu)
+            virCPUDefRef(cpu);
+        driver->hostcpu = cpu;
+    }
 }
 
 
@@ -300,17 +296,6 @@ qemuTestParseCapabilitiesArch(virArch arch,
 }
 
 
-virQEMUCapsPtr
-qemuTestParseCapabilities(virCapsPtr caps,
-                          const char *capsFile)
-{
-    if (!caps)
-        return NULL;
-
-    return qemuTestParseCapabilitiesArch(caps->host.arch, capsFile);
-}
-
-
 void qemuTestDriverFree(virQEMUDriver *driver)
 {
     virMutexDestroy(&driver->lock);
@@ -382,6 +367,12 @@ int qemuTestDriverInit(virQEMUDriver *driver)
 
     memset(driver, 0, sizeof(*driver));
 
+    if (!(cpuDefault = virCPUDefCopy(&cpuDefaultData)) ||
+        !(cpuHaswell = virCPUDefCopy(&cpuHaswellData)) ||
+        !(cpuPower8 = virCPUDefCopy(&cpuPower8Data)) ||
+        !(cpuPower9 = virCPUDefCopy(&cpuPower9Data)))
+        return -1;
+
     if (virMutexInit(&driver->lock) < 0)
         return -1;
 
@@ -439,6 +430,8 @@ int qemuTestDriverInit(virQEMUDriver *driver)
     if (!(driver->securityManager = virSecurityManagerNewStack(mgr)))
         goto error;
 
+    qemuTestSetHostCPU(driver, driver->hostarch, NULL);
+
     return 0;
 
  error:
diff --git a/tests/testutilsqemu.h b/tests/testutilsqemu.h
index 8dcc930ac3..edee6e450c 100644
--- a/tests/testutilsqemu.h
+++ b/tests/testutilsqemu.h
@@ -72,8 +72,6 @@ virDomainXMLOptionPtr testQemuXMLConfInit(void);
 
 virQEMUCapsPtr qemuTestParseCapabilitiesArch(virArch arch,
                                              const char *capsFile);
-virQEMUCapsPtr qemuTestParseCapabilities(virCapsPtr caps,
-                                         const char *capsFile);
 
 extern virCPUDefPtr cpuDefault;
 extern virCPUDefPtr cpuHaswell;
@@ -82,7 +80,8 @@ extern virCPUDefPtr cpuPower9;
 
 void qemuTestSetHostArch(virQEMUDriverPtr driver,
                          virArch arch);
-void qemuTestSetHostCPU(virCapsPtr caps,
+void qemuTestSetHostCPU(virQEMUDriverPtr driver,
+                        virArch arch,
                         virCPUDefPtr cpu);
 
 int qemuTestDriverInit(virQEMUDriver *driver);
-- 
2.23.0




More information about the libvir-list mailing list