[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