mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-20 06:50:22 +03: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);
|
||||
}
|
||||
|
||||
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,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
|
||||
virDomainLifecycleDefFormat(virBufferPtr buf,
|
||||
int type,
|
||||
@ -7733,6 +7981,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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user