mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
cputune: Implementations of parsing and formating cputune xml
Implementations of following functions: virDomainVcpupinIsDuplicate virDomainVcpupinFindByVcpu virDomainVcpupinAdd Update "virDomainDefParseXML" to parse, and "virDomainDefFormatXML" to build cputune xml, also implementations of new internal helper functions. v1 - v2: * Resolve potential crash bug of "virDomainVcpupinAdd"
This commit is contained in:
parent
853f0fdfd9
commit
b8853925fa
@ -848,6 +848,22 @@ virDomainClockDefClear(virDomainClockDefPtr def)
|
|||||||
VIR_FREE(def->timers);
|
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)
|
void virDomainDefFree(virDomainDefPtr def)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
@ -936,6 +952,8 @@ void virDomainDefFree(virDomainDefPtr def)
|
|||||||
|
|
||||||
virCPUDefFree(def->cpu);
|
virCPUDefFree(def->cpu);
|
||||||
|
|
||||||
|
virDomainVcpupinDefFree(def->cputune.vcpupin, def->cputune.nvcpupin);
|
||||||
|
|
||||||
virSysinfoDefFree(def->sysinfo);
|
virSysinfoDefFree(def->sysinfo);
|
||||||
|
|
||||||
if (def->namespaceData && def->ns.free)
|
if (def->namespaceData && def->ns.free)
|
||||||
@ -5089,6 +5107,76 @@ cleanup:
|
|||||||
return ret;
|
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,
|
static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
|
||||||
xmlDocPtr xml,
|
xmlDocPtr xml,
|
||||||
xmlNodePtr root,
|
xmlNodePtr root,
|
||||||
@ -5250,6 +5338,46 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
|
|||||||
VIR_FREE(tmp);
|
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);
|
n = virXPathNodeSet("./features/*", ctxt, &nodes);
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
goto error;
|
goto error;
|
||||||
@ -6502,6 +6630,126 @@ 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 {
|
||||||
|
if (virDomainVcpupinIsDuplicate(def->cputune.vcpupin,
|
||||||
|
def->cputune.nvcpupin,
|
||||||
|
vcpu)) {
|
||||||
|
vcpupin = virDomainVcpupinFindByVcpu(def->cputune.vcpupin,
|
||||||
|
def->cputune.nvcpupin,
|
||||||
|
vcpu);
|
||||||
|
vcpupin->vcpuid = vcpu;
|
||||||
|
vcpupin->cpumask = cpumask;
|
||||||
|
} else {
|
||||||
|
if (VIR_ALLOC(vcpupin) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VIR_REALLOC_N(def->cputune.vcpupin, def->cputune.nvcpupin + 1) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
VIR_FREE(vcpupin);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
vcpupin->vcpuid = vcpu;
|
||||||
|
vcpupin->cpumask = cpumask;
|
||||||
|
def->cputune.vcpupin[def->cputune.nvcpupin++] = vcpupin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(cpumask);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
virDomainLifecycleDefFormat(virBufferPtr buf,
|
virDomainLifecycleDefFormat(virBufferPtr buf,
|
||||||
int type,
|
int type,
|
||||||
@ -7733,6 +7981,36 @@ char *virDomainDefFormat(virDomainDefPtr def,
|
|||||||
virBufferVSprintf(&buf, " current='%u'", def->vcpus);
|
virBufferVSprintf(&buf, " current='%u'", def->vcpus);
|
||||||
virBufferVSprintf(&buf, ">%u</vcpu>\n", def->maxvcpus);
|
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)
|
if (def->sysinfo)
|
||||||
virDomainSysinfoDefFormat(&buf, def->sysinfo);
|
virDomainSysinfoDefFormat(&buf, def->sysinfo);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user