[libvirt] [PATCH] test: Refactor vcpu pinning and vcpu info retrieval

Peter Krempa pkrempa at redhat.com
Wed Jun 17 15:51:29 UTC 2015


Drop internal data structures and use the proper fields in virDomainDef.

This allows to greatly simplify the code and allows to remove the
private data structure that was holding just redundant data.

This patch also fixes the bogous output where we'd report that a fresh
VM without vCPU pinning would not run on all vcpus.
---

This applies on top of [PATCH 0/8] Test driver refactors and fixes:

 src/test/test_driver.c | 224 +++++++++++--------------------------------------
 1 file changed, 49 insertions(+), 175 deletions(-)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 9e617a2..f17d353 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -64,14 +64,6 @@

 VIR_LOG_INIT("test.test_driver");

-/* Driver specific info to carry with a domain */
-struct _testDomainObjPrivate {
-    virVcpuInfoPtr vcpu_infos;
-
-    unsigned char *cpumaps;
-};
-typedef struct _testDomainObjPrivate testDomainObjPrivate;
-typedef struct _testDomainObjPrivate *testDomainObjPrivatePtr;

 #define MAX_CPUS 128

@@ -170,25 +162,6 @@ testObjectEventQueueUnlocked(testConnPtr driver,
     testDriverUnlock(driver);
 }

-static void *testDomainObjPrivateAlloc(void)
-{
-    testDomainObjPrivatePtr priv;
-
-    if (VIR_ALLOC(priv) < 0)
-        return NULL;
-
-    return priv;
-}
-
-static void testDomainObjPrivateFree(void *data)
-{
-    testDomainObjPrivatePtr priv = data;
-
-    VIR_FREE(priv->vcpu_infos);
-    VIR_FREE(priv->cpumaps);
-    VIR_FREE(priv);
-}
-
 #define TEST_NAMESPACE_HREF "http://libvirt.org/schemas/domain/test/1.0"

 typedef struct _testDomainNamespaceDef testDomainNamespaceDef;
@@ -313,18 +286,13 @@ testDomainDefNamespaceParse(xmlDocPtr xml ATTRIBUTE_UNUSED,
 static virDomainXMLOptionPtr
 testBuildXMLConfig(void)
 {
-    virDomainXMLPrivateDataCallbacks priv = {
-        .alloc = testDomainObjPrivateAlloc,
-        .free = testDomainObjPrivateFree
-    };
-
     /* All our XML extensions are input only, so we only need to parse */
     virDomainXMLNamespace ns = {
         .parse = testDomainDefNamespaceParse,
         .free = testDomainDefNamespaceFree,
     };

-    return virDomainXMLOptionNew(NULL, &priv, &ns);
+    return virDomainXMLOptionNew(NULL, NULL, &ns);
 }


@@ -580,95 +548,6 @@ testDomainGenerateIfnames(virDomainDefPtr domdef)
     return 0;
 }

-/* Helper to update info for a single VCPU */
-static int
-testDomainUpdateVCPU(virDomainObjPtr dom,
-                     int vcpu,
-                     int maplen,
-                     int maxcpu)
-{
-    testDomainObjPrivatePtr privdata = dom->privateData;
-    virVcpuInfoPtr info = &privdata->vcpu_infos[vcpu];
-    unsigned char *cpumap = VIR_GET_CPUMAP(privdata->cpumaps, maplen, vcpu);
-    size_t j;
-    bool cpu;
-
-    memset(info, 0, sizeof(virVcpuInfo));
-    memset(cpumap, 0, maplen);
-
-    info->number    = vcpu;
-    info->state     = VIR_VCPU_RUNNING;
-    info->cpuTime   = 5000000;
-    info->cpu       = 0;
-
-    if (dom->def->cpumask) {
-        for (j = 0; j < maxcpu && j < VIR_DOMAIN_CPUMASK_LEN; ++j) {
-            if (virBitmapGetBit(dom->def->cpumask, j, &cpu) < 0)
-                return -1;
-            if (cpu) {
-                VIR_USE_CPU(cpumap, j);
-                info->cpu = j;
-            }
-        }
-    } else {
-        for (j = 0; j < maxcpu; ++j) {
-            if ((j % 3) == 0) {
-                /* Mark of every third CPU as usable */
-                VIR_USE_CPU(cpumap, j);
-                info->cpu = j;
-            }
-        }
-    }
-
-    return 0;
-}
-
-/*
- * Update domain VCPU amount and info
- *
- * @conn: virConnectPtr
- * @dom : domain needing updates
- * @nvcpus: New amount of vcpus for the domain
- * @clear_all: If true, rebuild info for ALL vcpus, not just newly added vcpus
- */
-static int
-testDomainUpdateVCPUs(testConnPtr privconn,
-                      virDomainObjPtr dom,
-                      int nvcpus,
-                      unsigned int clear_all)
-{
-    testDomainObjPrivatePtr privdata = dom->privateData;
-    size_t i;
-    int ret = -1;
-    int cpumaplen, maxcpu;
-
-    maxcpu  = VIR_NODEINFO_MAXCPUS(privconn->nodeInfo);
-    cpumaplen = VIR_CPU_MAPLEN(maxcpu);
-
-    if (VIR_REALLOC_N(privdata->vcpu_infos, nvcpus) < 0)
-        goto cleanup;
-
-    if (VIR_REALLOC_N(privdata->cpumaps, nvcpus * cpumaplen) < 0)
-        goto cleanup;
-
-    /* Set running VCPU and cpumap state */
-    if (clear_all) {
-        for (i = 0; i < nvcpus; ++i)
-            if (testDomainUpdateVCPU(dom, i, cpumaplen, maxcpu) < 0)
-                goto cleanup;
-
-    } else if (nvcpus > dom->def->vcpus) {
-        /* VCPU amount has grown, populate info for the new vcpus */
-        for (i = dom->def->vcpus; i < nvcpus; ++i)
-            if (testDomainUpdateVCPU(dom, i, cpumaplen, maxcpu) < 0)
-                goto cleanup;
-    }
-
-    dom->def->vcpus = nvcpus;
-    ret = 0;
- cleanup:
-    return ret;
-}

 static void
 testDomainShutdownState(virDomainPtr domain,
@@ -695,9 +574,6 @@ testDomainStartState(testConnPtr privconn,
 {
     int ret = -1;

-    if (testDomainUpdateVCPUs(privconn, dom, dom->def->vcpus, 1) < 0)
-        goto cleanup;
-
     virDomainObjSetState(dom, VIR_DOMAIN_RUNNING, reason);
     dom->def->id = privconn->nextDomID++;

@@ -2507,7 +2383,6 @@ static int
 testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
                         unsigned int flags)
 {
-    testConnPtr privconn = domain->conn->privateData;
     virDomainObjPtr privdom = NULL;
     virDomainDefPtr def;
     virDomainDefPtr persistentDef;
@@ -2544,9 +2419,8 @@ testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
         goto cleanup;
     }

-    if (def &&
-        testDomainUpdateVCPUs(privconn, privdom, nrCpus, 0) < 0)
-        goto cleanup;
+    if (def)
+        def->vcpus = nrCpus;

     if (persistentDef) {
         if (flags & VIR_DOMAIN_VCPU_MAXIMUM) {
@@ -2578,13 +2452,14 @@ static int testDomainGetVcpus(virDomainPtr domain,
                               int maplen)
 {
     testConnPtr privconn = domain->conn->privateData;
-    testDomainObjPrivatePtr privdomdata;
     virDomainObjPtr privdom;
+    virDomainDefPtr def;
     size_t i;
-    int v, maxcpu, hostcpus;
+    int maxcpu, hostcpus;
     int ret = -1;
     struct timeval tv;
     unsigned long long statbase;
+    virBitmapPtr allcpumap;

     if (!(privdom = testDomObjFromDomain(domain)))
         return -1;
@@ -2595,7 +2470,7 @@ static int testDomainGetVcpus(virDomainPtr domain,
         goto cleanup;
     }

-    privdomdata = privdom->privateData;
+    def = privdom->def;

     if (gettimeofday(&tv, NULL) < 0) {
         virReportSystemError(errno,
@@ -2605,45 +2480,47 @@ static int testDomainGetVcpus(virDomainPtr domain,

     statbase = (tv.tv_sec * 1000UL * 1000UL) + tv.tv_usec;

-
     hostcpus = VIR_NODEINFO_MAXCPUS(privconn->nodeInfo);
     maxcpu = maplen * 8;
     if (maxcpu > hostcpus)
         maxcpu = hostcpus;

+    if (!(allcpumap = virBitmapNew(hostcpus)))
+        goto cleanup;
+
+    virBitmapSetAll(allcpumap);
+
     /* Clamp to actual number of vcpus */
     if (maxinfo > privdom->def->vcpus)
         maxinfo = privdom->def->vcpus;

-    /* Populate virVcpuInfo structures */
-    if (info != NULL) {
-        memset(info, 0, sizeof(*info) * maxinfo);
+    memset(info, 0, sizeof(*info) * maxinfo);
+    memset(cpumaps, 0, maxinfo * maplen);

-        for (i = 0; i < maxinfo; i++) {
-            virVcpuInfo privinfo = privdomdata->vcpu_infos[i];
+    for (i = 0; i < maxinfo; i++) {
+        virDomainPinDefPtr pininfo;
+        virBitmapPtr bitmap = NULL;

-            info[i].number = privinfo.number;
-            info[i].state = privinfo.state;
-            info[i].cpu = privinfo.cpu;
+        pininfo = virDomainPinFind(def->cputune.vcpupin,
+                                   def->cputune.nvcpupin,
+                                   i);

-            /* Fake an increasing cpu time value */
-            info[i].cpuTime = statbase / 10;
-        }
-    }
+        if (pininfo && pininfo->cpumask)
+            bitmap = pininfo->cpumask;
+        else if (def->cpumask)
+            bitmap = def->cpumask;
+        else
+            bitmap = allcpumap;

-    /* Populate cpumaps */
-    if (cpumaps != NULL) {
-        int privmaplen = VIR_CPU_MAPLEN(hostcpus);
-        memset(cpumaps, 0, maplen * maxinfo);
+        if (cpumaps)
+            virBitmapToDataBuf(bitmap, VIR_GET_CPUMAP(cpumaps, maplen, i), maplen);

-        for (v = 0; v < maxinfo; v++) {
-            unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, v);
+        info[i].number = i;
+        info[i].state = VIR_VCPU_RUNNING;
+        info[i].cpu = virBitmapLastSetBit(bitmap);

-            for (i = 0; i < maxcpu; i++) {
-                if (VIR_CPU_USABLE(privdomdata->cpumaps, privmaplen, v, i))
-                    VIR_USE_CPU(cpumap, i);
-            }
-        }
+        /* Fake an increasing cpu time value */
+        info[i].cpuTime = statbase / 10;
     }

     ret = maxinfo;
@@ -2657,17 +2534,15 @@ static int testDomainPinVcpu(virDomainPtr domain,
                              unsigned char *cpumap,
                              int maplen)
 {
-    testConnPtr privconn = domain->conn->privateData;
-    testDomainObjPrivatePtr privdomdata;
     virDomainObjPtr privdom;
-    unsigned char *privcpumap;
-    size_t i;
-    int maxcpu, hostcpus, privmaplen;
+    virDomainDefPtr def;
     int ret = -1;

     if (!(privdom = testDomObjFromDomain(domain)))
         return -1;

+    def = privdom->def;
+
     if (!virDomainObjIsActive(privdom)) {
         virReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("cannot pin vcpus on an inactive domain"));
@@ -2680,20 +2555,19 @@ static int testDomainPinVcpu(virDomainPtr domain,
         goto cleanup;
     }

-    privdomdata = privdom->privateData;
-    hostcpus = VIR_NODEINFO_MAXCPUS(privconn->nodeInfo);
-    privmaplen = VIR_CPU_MAPLEN(hostcpus);
-
-    maxcpu = maplen * 8;
-    if (maxcpu > hostcpus)
-        maxcpu = hostcpus;
-
-    privcpumap = VIR_GET_CPUMAP(privdomdata->cpumaps, privmaplen, vcpu);
-    memset(privcpumap, 0, privmaplen);
-
-    for (i = 0; i < maxcpu; i++) {
-        if (VIR_CPU_USABLE(cpumap, maplen, 0, i))
-            VIR_USE_CPU(privcpumap, i);
+    if (!def->cputune.vcpupin) {
+        if (VIR_ALLOC(def->cputune.vcpupin) < 0)
+            goto cleanup;
+        def->cputune.nvcpupin = 0;
+    }
+    if (virDomainPinAdd(&def->cputune.vcpupin,
+                        &def->cputune.nvcpupin,
+                        cpumap,
+                        maplen,
+                        vcpu) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("failed to update or add vcpupin"));
+        goto cleanup;
     }

     ret = 0;
-- 
2.4.1




More information about the libvir-list mailing list