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

Daniel Veillard veillard at redhat.com
Tue Mar 29 08:01:09 UTC 2011


On Tue, Mar 29, 2011 at 02:32:22PM +0800, Osier Yang wrote:
> 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);

 ACK,

Daniel

-- 
Daniel Veillard      | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
daniel at veillard.com  | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library  http://libvirt.org/




More information about the libvir-list mailing list