[libvirt] [PATCH v2 1/2] XML definitions for guest NUMA and parsing routines

Daniel P. Berrange berrange at redhat.com
Tue Nov 15 11:48:53 UTC 2011


On Fri, Nov 11, 2011 at 06:21:45PM +0530, Bharata B Rao wrote:
> XML definitions for guest NUMA and parsing routines.
> 
> From: Bharata B Rao <bharata at linux.vnet.ibm.com>
> 
> This patch adds XML definitions for guest NUMA specification and contains
> routines to parse the same. The guest NUMA specification looks like this:
> 
> <cpu>
>         ...
>         <topology sockets='2' cores='4' threads='2'/>
>         <numa>
>                 <cell cpus='0-7' memory='512000'/>
>                 <cell cpus='8-15' memory='512000'/>
>         </numa>
>         ...
> </cpu>
> 
> Signed-off-by: Bharata B Rao <bharata at linux.vnet.ibm.com>
> ---
> 
>  docs/formatdomain.html.in     |   29 ++++++++++++++
>  docs/schemas/domaincommon.rng |   31 ++++++++++++++-
>  src/conf/cpu_conf.c           |   86 ++++++++++++++++++++++++++++++++++++++++-
>  src/conf/cpu_conf.h           |   13 ++++++
>  src/conf/domain_conf.c        |    7 +++
>  5 files changed, 163 insertions(+), 3 deletions(-)
> 
> 
> diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
> index cbad196..28a4edc 100644
> --- a/docs/formatdomain.html.in
> +++ b/docs/formatdomain.html.in
> @@ -628,6 +628,35 @@
>        </dd>
>      </dl>
>  
> +    <p>
> +      Guest NUMA topology can be specifed using  <code>numa</code> element.
> +      <span class="since">Since 0.9.8</span>
> +    </p>
> +
> +<pre>
> +  ...
> +  <cpu>
> +    ...
> +    <numa>
> +      <cell cpus='0-3' memory='512000'/>
> +      <cell cpus='4-7' memory='512000'/>
> +    </numa>
> +    ...
> +  </cpu>
> +  ...</pre>
> +
> +    <p>
> +      Each <code>cell</code> element specifies a NUMA cell or a NUMA node.
> +      <code>cpus</code> specifies the CPU or range of CPUs that are part of
> +      the node. <code>memory</code> specifies the node memory in kilobytes
> +      (i.e. blocks of 1024 bytes). Each cell or node is assigned cellid
> +      or nodeid in the increasing order starting from 0.
> +    </p>
> +
> +    <p>
> +      This guest NUMA specification is currently available only for QEMU/KVM.
> +    </p>
> +
>      <h3><a name="elementsLifecycle">Lifecycle control</a></h3>
>  
>      <p>
> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
> index b6f858e..afcaccc 100644
> --- a/docs/schemas/domaincommon.rng
> +++ b/docs/schemas/domaincommon.rng
> @@ -2297,7 +2297,14 @@
>    <define name="cpu">
>      <element name="cpu">
>        <choice>
> -        <ref name="cpuTopology"/>
> +        <group>
> +          <optional>
> +            <ref name="cpuTopology"/>
> +          </optional>  
> +          <optional>
> +            <ref name="cpuNuma"/>
> +          </optional>
> +        </group>
>          <group>
>            <ref name="cpuMatch"/>
>            <interleave>
> @@ -2311,6 +2318,9 @@
>              <zeroOrMore>
>                <ref name="cpuFeature"/>
>              </zeroOrMore>
> +            <optional>
> +              <ref name="cpuNuma"/>
> +            </optional>
>            </interleave>
>          </group>
>        </choice>
> @@ -2371,6 +2381,25 @@
>      </element>
>    </define>
>  
> +  <define name="cpuNuma">
> +    <element name="numa">
> +      <oneOrMore>
> +        <ref name="numaCell"/>
> +      </oneOrMore>
> +    </element>
> +  </define>
> +
> +  <define name="numaCell">
> +    <element name="cell">
> +      <attribute name="cpus">
> +        <ref name="cpuset"/>
> +      </attribute>
> +      <attribute name="memory">
> +        <ref name="memoryKB"/>
> +      </attribute>
> +    </element>
> +  </define>
> +
>    <!--
>        System information specification:
>         Placeholder for system specific informations likes the ones
> diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c
> index 41e997e..4aabe98 100644
> --- a/src/conf/cpu_conf.c
> +++ b/src/conf/cpu_conf.c
> @@ -28,6 +28,7 @@
>  #include "util.h"
>  #include "buf.h"
>  #include "cpu_conf.h"
> +#include "domain_conf.h"
>  
>  #define VIR_FROM_THIS VIR_FROM_CPU
>  
> @@ -67,6 +68,12 @@ virCPUDefFree(virCPUDefPtr def)
>          VIR_FREE(def->features[i].name);
>      VIR_FREE(def->features);
>  
> +    for (i = 0 ; i < def->ncells ; i++) {
> +        VIR_FREE(def->cells[i].cpumask);
> +        VIR_FREE(def->cells[i].cpustr);
> +    }
> +    VIR_FREE(def->cells);
> +
>      VIR_FREE(def);
>  }
>  
> @@ -109,7 +116,6 @@ no_memory:
>      return NULL;
>  }
>  
> -
>  virCPUDefPtr
>  virCPUDefParseXML(const xmlNodePtr node,
>                    xmlXPathContextPtr ctxt,
> @@ -289,9 +295,75 @@ virCPUDefParseXML(const xmlNodePtr node,
>          def->features[i].policy = policy;
>      }
>  
> +    if (virXPathNode("./numa[1]", ctxt)) {
> +        VIR_FREE(nodes);
> +        n = virXPathNodeSet("./numa[1]/cell", ctxt, &nodes);
> +        if (n <= 0) {
> +            virCPUReportError(VIR_ERR_INTERNAL_ERROR,
> +                    "%s", _("NUMA topology defined without NUMA cells"));
> +            goto error;
> +        }
> +
> +        if (VIR_RESIZE_N(def->cells, def->ncells_max,
> +                         def->ncells, n) < 0)
> +            goto no_memory;
> +
> +        def->ncells = n;
> +
> +        for (i = 0 ; i < n ; i++) {
> +            char *cpus, *cpus_parse, *memory;
> +            int cpumasklen = VIR_DOMAIN_CPUMASK_LEN;
> +            int ret, ncpus = 0;
> +
> +            def->cells[i].cellid = i;
> +            cpus = cpus_parse = virXMLPropString(nodes[i], "cpus");
> +            if (!cpus) {
> +                virCPUReportError(VIR_ERR_INTERNAL_ERROR,
> +                    "%s", _("Missing 'cpus' attribute in NUMA cell"));
> +                goto error;
> +            }
> +
> +            def->cells[i].cpustr = strdup(cpus);
> +            if (!def->cells[i].cpustr) {
> +                VIR_FREE(cpus);
> +                goto no_memory;
> +            }
> +
> +            if (VIR_ALLOC_N(def->cells[i].cpumask, cpumasklen) < 0) {
> +                VIR_FREE(cpus);
> +                goto no_memory;
> +            }
> +
> +            ncpus = virDomainCpuSetParse((const char **)&cpus_parse,
> +                                 0, def->cells[i].cpumask, cpumasklen);
> +            if (ncpus <= 0) {
> +                VIR_FREE(cpus);
> +                goto error;
> +            }
> +            def->cells_cpus += ncpus;
> +
> +            memory = virXMLPropString(nodes[i], "memory");
> +            if (!memory) {
> +                virCPUReportError(VIR_ERR_INTERNAL_ERROR,
> +                    "%s", _("Missing 'memory' attribute in NUMA cell"));
> +                VIR_FREE(cpus);
> +                goto error;
> +            }
> +
> +            ret  = virStrToLong_ui(memory, NULL, 10, &def->cells[i].mem);
> +            if (ret == -1) {
> +                VIR_FREE(cpus);
> +                VIR_FREE(memory);
> +                goto error;
> +            }
> +
> +            VIR_FREE(cpus);
> +            VIR_FREE(memory);
> +        }
> +    }
> +
>  cleanup:
>      VIR_FREE(nodes);
> -
>      return def;
>  
>  no_memory:
> @@ -414,6 +486,16 @@ virCPUDefFormatBuf(virBufferPtr buf,
>          }
>      }
>  
> +    if (def->ncells) {
> +        virBufferAddLit(buf, "<numa>\n");
> +        for (i = 0; i < def->ncells; i++) {
> +            virBufferAddLit(buf, "  <cell");
> +            virBufferAsprintf(buf, " cpus='%s'", def->cells[i].cpustr);
> +            virBufferAsprintf(buf, " memory='%d'", def->cells[i].mem);
> +            virBufferAddLit(buf, "/>\n");
> +        }
> +        virBufferAddLit(buf, "</numa>\n");
> +    }
>      return 0;
>  }
>  
> diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h
> index 4406cba..efff473 100644
> --- a/src/conf/cpu_conf.h
> +++ b/src/conf/cpu_conf.h
> @@ -67,6 +67,15 @@ struct _virCPUFeatureDef {
>      int policy;         /* enum virCPUFeaturePolicy */
>  };
>  
> +typedef struct _virCellDef virCellDef;
> +typedef virCellDef *virCellDefPtr;
> +struct _virCellDef {
> +   int cellid;
> +   char *cpumask;	/* CPUs that are part of this node */
> +   char *cpustr;	/* CPUs stored in string form for dumpxml */
> +   unsigned int mem;	/* Node memory in kB */
> +};
> +
>  typedef struct _virCPUDef virCPUDef;
>  typedef virCPUDef *virCPUDefPtr;
>  struct _virCPUDef {
> @@ -81,6 +90,10 @@ struct _virCPUDef {
>      size_t nfeatures;
>      size_t nfeatures_max;
>      virCPUFeatureDefPtr features;
> +    size_t ncells;
> +    size_t ncells_max;
> +    virCellDefPtr cells;
> +    unsigned int cells_cpus;
>  };
>  
>  
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index a85f837..1203119 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -7572,6 +7572,13 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
>  
>          if (def->cpu == NULL)
>              goto error;
> +
> +        if (def->cpu->cells_cpus > def->maxvcpus) {
> +            virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                                 _("Number of CPUs in <numa> exceeds the"
> +                                   " <vcpu> count"));
> +            goto error;
> +        }
>      }
>  
>      if ((node = virXPathNode("./sysinfo[1]", ctxt)) != NULL) {

ACK


Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|




More information about the libvir-list mailing list