[libvirt] [PATCH 4/8] cputune: implementations of parsing and formating cputune xml

Osier Yang jyang at redhat.com
Tue Mar 29 06:32:22 UTC 2011


implementations of following functions:
  virDomainVcpupinIsDuplicate
  virDomainVcpupinFindByVcpu
  virDomainVcpupinAdd

Update "virDomainDefParseXML" to parse, and "virDomainDefFormatXML"
to build cputune xml, also implementations of new internal helper
functions.
---
 src/conf/domain_conf.c |  280 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 280 insertions(+), 0 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index b681dc3..e9775be 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -848,6 +848,22 @@ virDomainClockDefClear(virDomainClockDefPtr def)
     VIR_FREE(def->timers);
 }

+static void
+virDomainVcpupinDefFree(virDomainVcpupinDefPtr *def,
+                        int nvcpupin)
+{
+    int i;
+
+    if (!def || !nvcpupin)
+        return;
+
+    for(i = 0; i < nvcpupin; i++) {
+        VIR_FREE(def[i]);
+    }
+
+    VIR_FREE(def);
+}
+
 void virDomainDefFree(virDomainDefPtr def)
 {
     unsigned int i;
@@ -936,6 +952,8 @@ void virDomainDefFree(virDomainDefPtr def)

     virCPUDefFree(def->cpu);

+    virDomainVcpupinDefFree(def->cputune.vcpupin, def->cputune.nvcpupin);
+
     virSysinfoDefFree(def->sysinfo);

     if (def->namespaceData && def->ns.free)
@@ -5089,6 +5107,76 @@ cleanup:
     return ret;
 }

+/* Parse the XML definition for a vcpupin */
+static virDomainVcpupinDefPtr
+virDomainVcpupinDefParseXML(const xmlNodePtr node,
+                            xmlXPathContextPtr ctxt,
+                            int maxvcpus,
+                            int flags ATTRIBUTE_UNUSED)
+{
+    virDomainVcpupinDefPtr def;
+    xmlNodePtr oldnode = ctxt->node;
+    unsigned int vcpuid;
+    char *tmp = NULL;
+    int ret;
+
+    if (VIR_ALLOC(def) < 0) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    ctxt->node = node;
+
+    ret = virXPathUInt("string(./@vcpu)", ctxt, &vcpuid);
+    if (ret == -2) {
+        virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                             "%s", _("vcpu id must be an unsigned integer"));
+        goto error;
+    } else if (ret == -1) {
+        virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                             "%s", _("can't parse vcpupin node"));
+        goto error;
+    }
+
+    if (vcpuid >= maxvcpus) {
+        virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                             "%s", _("vcpu id must be less than maxvcpus"));
+        goto error;
+    }
+
+    def->vcpuid = vcpuid;
+
+    tmp = virXMLPropString(node, "cpuset");
+
+    if (tmp) {
+        char *set = tmp;
+        int cpumasklen = VIR_DOMAIN_CPUMASK_LEN;
+
+        if (VIR_ALLOC_N(def->cpumask, cpumasklen) < 0) {
+            virReportOOMError();
+            goto error;
+        }
+        if (virDomainCpuSetParse((const char **)&set,
+                                 0, def->cpumask,
+                                 cpumasklen) < 0)
+           goto error;
+        VIR_FREE(tmp);
+    } else {
+        virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                             "%s", _("missing cpuset for vcpupin"));
+        goto error;
+    }
+
+cleanup:
+    ctxt->node = oldnode;
+    return def;
+
+error:
+    VIR_FREE(def);
+    goto cleanup;
+}
+
+
 static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
                                             xmlDocPtr xml,
                                             xmlNodePtr root,
@@ -5250,6 +5338,46 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
         VIR_FREE(tmp);
     }

+    /* Extract cpu tunables. */
+    if (virXPathULong("string(./cputune/shares[1])", ctxt,
+                      &def->cputune.shares) < 0)
+        def->cputune.shares = 0;
+
+    if ((n = virXPathNodeSet("./cputune/vcpupin", ctxt, &nodes)) < 0) {
+        virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                             "%s", _("cannot extract vcpupin nodes"));
+        goto error;
+    }
+
+    if (n && VIR_ALLOC_N(def->cputune.vcpupin, n) < 0)
+        goto no_memory;
+
+    if (n > def->maxvcpus) {
+        virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                             "%s", _("vcpupin nodes must be less than maxvcpus"));
+        goto error;
+    }
+
+    for (i = 0 ; i < n ; i++) {
+        virDomainVcpupinDefPtr vcpupin = NULL;
+        vcpupin = virDomainVcpupinDefParseXML(nodes[i], ctxt, def->maxvcpus, 0);
+
+        if (!vcpupin)
+            goto error;
+
+        if (virDomainVcpupinIsDuplicate(def->cputune.vcpupin,
+                                        def->cputune.nvcpupin,
+                                        vcpupin->vcpuid)) {
+            virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                                 "%s", _("duplicate vcpupin for same vcpu"));
+            VIR_FREE(vcpupin);
+            goto error;
+        }
+
+        def->cputune.vcpupin[def->cputune.nvcpupin++] = vcpupin;
+    }
+    VIR_FREE(nodes);
+
     n = virXPathNodeSet("./features/*", ctxt, &nodes);
     if (n < 0)
         goto error;
@@ -6502,6 +6630,128 @@ virDomainCpuSetParse(const char **str, char sep,
 }


+/* Check if vcpupin with same vcpuid already exists.
+ * Return 1 if exists, 0 if not. */
+int
+virDomainVcpupinIsDuplicate(virDomainVcpupinDefPtr *def,
+                            int nvcpupin,
+                            int vcpu)
+{
+    int i;
+
+    if (!def || !nvcpupin)
+        return 0;
+
+    for (i = 0; i < nvcpupin; i++) {
+        if (def[i]->vcpuid == vcpu)
+            return 1;
+    }
+
+    return 0;
+}
+
+virDomainVcpupinDefPtr
+virDomainVcpupinFindByVcpu(virDomainVcpupinDefPtr *def,
+                           int nvcpupin,
+                           int vcpu)
+{
+    int i;
+
+    if (!def || !nvcpupin)
+        return NULL;
+
+    for (i = 0; i < nvcpupin; i++) {
+        if (def[i]->vcpuid == vcpu)
+            return def[i];
+    }
+
+    return NULL;
+}
+
+int
+virDomainVcpupinAdd(virDomainDefPtr def,
+                    unsigned char *cpumap,
+                    int maplen,
+                    int vcpu)
+{
+    virDomainVcpupinDefPtr *vcpupin_list = NULL;
+    virDomainVcpupinDefPtr vcpupin = NULL;
+    char *cpumask = NULL;
+    int i;
+
+    if (VIR_ALLOC_N(cpumask, VIR_DOMAIN_CPUMASK_LEN) < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    /* Reset cpumask to all 0s. */
+    for (i = 0; i < VIR_DOMAIN_CPUMASK_LEN; i++)
+        cpumask[i] = 0;
+
+    /* Convert bitmap (cpumap) to cpumask, which is byte map? */
+    for (i = 0; i < maplen; i++) {
+        int cur;
+
+        for (cur = 0; cur < 8; cur++) {
+            if (cpumap[i] & (1 << cur))
+                cpumask[i * 8 + cur] = 1;
+        }
+    }
+
+    /* No vcpupin exists yet. */
+    if (!def->cputune.nvcpupin) {
+        if (VIR_ALLOC(vcpupin) < 0) {
+            virReportOOMError();
+            goto cleanup;
+        }
+
+        if (VIR_ALLOC(vcpupin_list) < 0) {
+            virReportOOMError();
+            VIR_FREE(vcpupin);
+            goto cleanup;
+        }
+
+        vcpupin->vcpuid = vcpu;
+        vcpupin->cpumask = cpumask;
+        vcpupin_list[def->cputune.nvcpupin++] = vcpupin;
+
+        def->cputune.vcpupin = vcpupin_list;
+    } else {
+        vcpupin_list = def->cputune.vcpupin;
+
+        if (virDomainVcpupinIsDuplicate(vcpupin_list,
+                                        def->cputune.nvcpupin,
+                                        vcpu)) {
+            vcpupin = virDomainVcpupinFindByVcpu(vcpupin_list,
+                                                 def->cputune.nvcpupin,
+                                                 vcpu);
+            vcpupin->vcpuid = vcpu;
+            vcpupin->cpumask = cpumask;
+        } else {
+            if (VIR_ALLOC(vcpupin) < 0) {
+                virReportOOMError();
+                goto cleanup;
+            }
+
+            if (VIR_REALLOC_N(vcpupin_list, def->cputune.nvcpupin + 1) < 0) {
+                virReportOOMError();
+                VIR_FREE(vcpupin);
+                goto cleanup;
+            }
+
+            vcpupin->vcpuid = vcpu;
+            vcpupin->cpumask = cpumask;
+            vcpupin_list[def->cputune.nvcpupin++] = vcpupin;
+       }
+    }
+
+    return 0;
+
+cleanup:
+    VIR_FREE(cpumask);
+    return -1;
+}
+
 static int
 virDomainLifecycleDefFormat(virBufferPtr buf,
                             int type,
@@ -7733,6 +7983,36 @@ char *virDomainDefFormat(virDomainDefPtr def,
         virBufferVSprintf(&buf, " current='%u'", def->vcpus);
     virBufferVSprintf(&buf, ">%u</vcpu>\n", def->maxvcpus);

+    if (def->cputune.shares || def->cputune.vcpupin)
+        virBufferAddLit(&buf, "  <cputune>\n");
+
+    if (def->cputune.shares)
+        virBufferVSprintf(&buf, "    <shares>%lu</shares>\n",
+                          def->cputune.shares);
+    if (def->cputune.vcpupin) {
+        int i;
+        for (i = 0; i < def->cputune.nvcpupin; i++) {
+            virBufferVSprintf(&buf, "    <vcpupin vcpu='%u' ",
+                              def->cputune.vcpupin[i]->vcpuid);
+
+            char *cpumask = NULL;
+            cpumask = virDomainCpuSetFormat(def->cputune.vcpupin[i]->cpumask,
+                                            VIR_DOMAIN_CPUMASK_LEN);
+
+            if (cpumask == NULL) {
+                virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                                     "%s", _("failed to format cpuset for vcpupin"));
+                goto cleanup;
+            }
+
+            virBufferVSprintf(&buf, "cpuset='%s'/>\n", cpumask);
+            VIR_FREE(cpumask);
+        }
+    }
+
+    if (def->cputune.shares || def->cputune.vcpupin)
+        virBufferAddLit(&buf, "  </cputune>\n");
+
     if (def->sysinfo)
         virDomainSysinfoDefFormat(&buf, def->sysinfo);

--
1.7.4




More information about the libvir-list mailing list