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@xxxxxxxxxxxx | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list