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(a)veillard.com | Rpmfind RPM search engine
http://rpmfind.net/
http://veillard.com/ | virtualization library
http://libvirt.org/