virsh: Add a helper to parse cpulist

The 'virsh vcpupin' and 'virsh emulatorpin' commands use the same
code to parse the cpulist. This patch abstracts the same code as
a helper. Along with various code style fixes, and error improvement
(only error "Physical CPU %d doesn't exist" if the specified CPU
exceed the range, no "cpulist: Invalid format", see the following
for an example of the error prior to this patch).

% virsh vcpupin 4 0 0-8
error: Physical CPU 4 doesn't exist.
error: cpulist: Invalid format.
This commit is contained in:
Osier Yang 2013-03-28 19:36:30 +08:00
parent 9a80050e52
commit 8893df388e
1 changed files with 106 additions and 172 deletions

View File

@ -5460,6 +5460,97 @@ vshPrintPinInfo(unsigned char *cpumaps, size_t cpumaplen,
return true;
}
static unsigned char *
vshParseCPUList(vshControl *ctl, const char *cpulist,
int maxcpu, size_t cpumaplen)
{
unsigned char *cpumap = NULL;
const char *cur;
bool unuse = false;
int i, cpu, lastcpu;
cpumap = vshCalloc(ctl, cpumaplen, sizeof(*cpumap));
/* Parse cpulist */
cur = cpulist;
if (*cur == 'r') {
for (cpu = 0; cpu < maxcpu; cpu++)
VIR_USE_CPU(cpumap, cpu);
return cpumap;
} else if (*cur == 0) {
goto error;
}
while (*cur != 0) {
/* The char '^' denotes exclusive */
if (*cur == '^') {
cur++;
unuse = true;
}
/* Parse physical CPU number */
if (!c_isdigit(*cur))
goto error;
if ((cpu = virParseNumber(&cur)) < 0)
goto error;
if (cpu >= maxcpu) {
vshError(ctl, _("Physical CPU %d doesn't exist."), cpu);
goto cleanup;
}
virSkipSpaces(&cur);
if (*cur == ',' || *cur == 0) {
if (unuse)
VIR_UNUSE_CPU(cpumap, cpu);
else
VIR_USE_CPU(cpumap, cpu);
} else if (*cur == '-') {
/* The char '-' denotes range */
if (unuse)
goto error;
cur++;
virSkipSpaces(&cur);
/* Parse the end of range */
lastcpu = virParseNumber(&cur);
if (lastcpu < cpu)
goto error;
if (lastcpu >= maxcpu) {
vshError(ctl, _("Physical CPU %d doesn't exist."), lastcpu);
goto cleanup;
}
for (i = cpu; i <= lastcpu; i++)
VIR_USE_CPU(cpumap, i);
virSkipSpaces(&cur);
}
if (*cur == ',') {
cur++;
virSkipSpaces(&cur);
unuse = false;
} else if (*cur == 0) {
break;
} else {
goto error;
}
}
return cpumap;
error:
vshError(ctl, "%s", _("cpulist: Invalid format."));
cleanup:
VIR_FREE(cpumap);
return NULL;
}
static bool
cmdVcpuPin(vshControl *ctl, const vshCmd *cmd)
{
@ -5467,13 +5558,11 @@ cmdVcpuPin(vshControl *ctl, const vshCmd *cmd)
virDomainPtr dom;
int vcpu = -1;
const char *cpulist = NULL;
bool ret = true;
bool ret = false;
unsigned char *cpumap = NULL;
unsigned char *cpumaps = NULL;
size_t cpumaplen;
int i, cpu, lastcpu, maxcpu, ncpus;
bool unuse = false;
const char *cur;
int i, maxcpu, ncpus;
bool config = vshCommandOptBool(cmd, "config");
bool live = vshCommandOptBool(cmd, "live");
bool current = vshCommandOptBool(cmd, "current");
@ -5545,7 +5634,6 @@ cmdVcpuPin(vshControl *ctl, const vshCmd *cmd)
vshPrint(ctl, "%s %s\n", _("VCPU:"), _("CPU Affinity"));
vshPrint(ctl, "----------------------------------\n");
for (i = 0; i < ncpus; i++) {
if (vcpu != -1 && i != vcpu)
continue;
@ -5556,105 +5644,28 @@ cmdVcpuPin(vshControl *ctl, const vshCmd *cmd)
break;
}
} else {
ret = false;
}
VIR_FREE(cpumaps);
goto cleanup;
}
/* Pin mode: pinning specified vcpu to specified physical cpus*/
cpumap = vshCalloc(ctl, cpumaplen, sizeof(*cpumap));
/* Parse cpulist */
cur = cpulist;
if (*cur == 0) {
goto parse_error;
} else if (*cur == 'r') {
for (cpu = 0; cpu < maxcpu; cpu++)
VIR_USE_CPU(cpumap, cpu);
cur = "";
}
while (*cur != 0) {
/* the char '^' denotes exclusive */
if (*cur == '^') {
cur++;
unuse = true;
}
/* parse physical CPU number */
if (!c_isdigit(*cur))
goto parse_error;
cpu = virParseNumber(&cur);
if (cpu < 0) {
goto parse_error;
}
if (cpu >= maxcpu) {
vshError(ctl, _("Physical CPU %d doesn't exist."), cpu);
goto parse_error;
}
virSkipSpaces(&cur);
if (*cur == ',' || *cur == 0) {
if (unuse) {
VIR_UNUSE_CPU(cpumap, cpu);
} else {
VIR_USE_CPU(cpumap, cpu);
}
} else if (*cur == '-') {
/* the char '-' denotes range */
if (unuse) {
goto parse_error;
}
cur++;
virSkipSpaces(&cur);
/* parse the end of range */
lastcpu = virParseNumber(&cur);
if (lastcpu < cpu) {
goto parse_error;
}
if (lastcpu >= maxcpu) {
vshError(ctl, _("Physical CPU %d doesn't exist."), maxcpu);
goto parse_error;
}
for (i = cpu; i <= lastcpu; i++) {
VIR_USE_CPU(cpumap, i);
}
virSkipSpaces(&cur);
}
if (*cur == ',') {
cur++;
virSkipSpaces(&cur);
unuse = false;
} else if (*cur == 0) {
break;
} else {
goto parse_error;
}
}
if (!(cpumap = vshParseCPUList(ctl, cpulist, maxcpu, cpumaplen)))
goto cleanup;
if (flags == -1) {
if (virDomainPinVcpu(dom, vcpu, cpumap, cpumaplen) != 0) {
ret = false;
}
if (virDomainPinVcpu(dom, vcpu, cpumap, cpumaplen) != 0)
goto cleanup;
} else {
if (virDomainPinVcpuFlags(dom, vcpu, cpumap, cpumaplen, flags) != 0) {
ret = false;
}
if (virDomainPinVcpuFlags(dom, vcpu, cpumap, cpumaplen, flags) != 0)
goto cleanup;
}
ret = true;
cleanup:
VIR_FREE(cpumap);
virDomainFree(dom);
return ret;
parse_error:
vshError(ctl, "%s", _("cpulist: Invalid format."));
ret = false;
goto cleanup;
}
/*
@ -5701,13 +5712,11 @@ cmdEmulatorPin(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
const char *cpulist = NULL;
bool ret = true;
bool ret = false;
unsigned char *cpumap = NULL;
unsigned char *cpumaps = NULL;
size_t cpumaplen;
int i, cpu, lastcpu, maxcpu;
bool unuse = false;
const char *cur;
int maxcpu;
bool config = vshCommandOptBool(cmd, "config");
bool live = vshCommandOptBool(cmd, "live");
bool current = vshCommandOptBool(cmd, "current");
@ -5761,101 +5770,26 @@ cmdEmulatorPin(vshControl *ctl, const vshCmd *cmd)
vshPrint(ctl, " *: ");
ret = vshPrintPinInfo(cpumaps, cpumaplen, maxcpu, 0);
vshPrint(ctl, "\n");
} else {
ret = false;
}
VIR_FREE(cpumaps);
goto cleanup;
}
/* Pin mode: pinning emulator threads to specified physical cpus*/
cpumap = vshCalloc(ctl, cpumaplen, sizeof(*cpumap));
/* Parse cpulist */
cur = cpulist;
if (*cur == 0) {
goto parse_error;
} else if (*cur == 'r') {
for (cpu = 0; cpu < maxcpu; cpu++)
VIR_USE_CPU(cpumap, cpu);
cur = "";
}
while (*cur != 0) {
/* the char '^' denotes exclusive */
if (*cur == '^') {
cur++;
unuse = true;
}
/* parse physical CPU number */
if (!c_isdigit(*cur))
goto parse_error;
cpu = virParseNumber(&cur);
if (cpu < 0) {
goto parse_error;
}
if (cpu >= maxcpu) {
vshError(ctl, _("Physical CPU %d doesn't exist."), cpu);
goto parse_error;
}
virSkipSpaces(&cur);
if (*cur == ',' || *cur == 0) {
if (unuse) {
VIR_UNUSE_CPU(cpumap, cpu);
} else {
VIR_USE_CPU(cpumap, cpu);
}
} else if (*cur == '-') {
/* the char '-' denotes range */
if (unuse) {
goto parse_error;
}
cur++;
virSkipSpaces(&cur);
/* parse the end of range */
lastcpu = virParseNumber(&cur);
if (lastcpu < cpu) {
goto parse_error;
}
if (lastcpu >= maxcpu) {
vshError(ctl, _("Physical CPU %d doesn't exist."), maxcpu);
goto parse_error;
}
for (i = cpu; i <= lastcpu; i++) {
VIR_USE_CPU(cpumap, i);
}
virSkipSpaces(&cur);
}
if (*cur == ',') {
cur++;
virSkipSpaces(&cur);
unuse = false;
} else if (*cur == 0) {
break;
} else {
goto parse_error;
}
}
if (!(cpumap = vshParseCPUList(ctl, cpulist, maxcpu, cpumaplen)))
goto cleanup;
if (flags == -1)
flags = VIR_DOMAIN_AFFECT_LIVE;
if (virDomainPinEmulator(dom, cpumap, cpumaplen, flags) != 0)
ret = false;
goto cleanup;
ret = true;
cleanup:
VIR_FREE(cpumap);
virDomainFree(dom);
return ret;
parse_error:
vshError(ctl, "%s", _("cpulist: Invalid format."));
ret = false;
goto cleanup;
}
/*