--- tools/virsh-domain.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++++++ tools/virsh.pod | 16 +++++ 2 files changed, 204 insertions(+) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 047d374..95015ad 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -4769,6 +4769,193 @@ parse_error: } /* + * "emulatorpin" command + */ +static const vshCmdInfo info_emulatorpin[] = { + {"help", N_("control or query domain emulator affinity")}, + {"desc", N_("Pin domain emulator threads to host physical CPUs.")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_emulatorpin[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, + {"cpulist", VSH_OT_DATA, VSH_OFLAG_EMPTY_OK, + N_("host cpu number(s) to set, or omit option to query")}, + {"config", VSH_OT_BOOL, 0, N_("affect next boot")}, + {"live", VSH_OT_BOOL, 0, N_("affect running domain")}, + {"current", VSH_OT_BOOL, 0, N_("affect current domain")}, + {NULL, 0, 0, NULL} +}; + +static bool +cmdEmulatorPin(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom; + virNodeInfo nodeinfo; + const char *cpulist = NULL; + bool ret = true; + unsigned char *cpumap = NULL; + unsigned char *cpumaps = NULL; + size_t cpumaplen; + int i, cpu, lastcpu, maxcpu; + bool unuse = false; + const char *cur; + bool config = vshCommandOptBool(cmd, "config"); + bool live = vshCommandOptBool(cmd, "live"); + bool current = vshCommandOptBool(cmd, "current"); + bool query = false; /* Query mode if no cpulist */ + unsigned int flags = 0; + + if (current) { + if (live || config) { + vshError(ctl, "%s", _("--current must be specified exclusively")); + return false; + } + flags = VIR_DOMAIN_AFFECT_CURRENT; + } else { + if (config) + flags |= VIR_DOMAIN_AFFECT_CONFIG; + if (live) + flags |= VIR_DOMAIN_AFFECT_LIVE; + /* neither option is specified */ + if (!live && !config) + flags = -1; + } + + if (!vshConnectionUsability(ctl, ctl->conn)) + return false; + + if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + return false; + + if (vshCommandOptString(cmd, "cpulist", &cpulist) < 0) { + vshError(ctl, "%s", _("emulatorpin: Missing cpulist.")); + virDomainFree(dom); + return false; + } + query = !cpulist; + + if (virNodeGetInfo(ctl->conn, &nodeinfo) != 0) { + virDomainFree(dom); + return false; + } + + maxcpu = VIR_NODEINFO_MAXCPUS(nodeinfo); + cpumaplen = VIR_CPU_MAPLEN(maxcpu); + + /* Query mode: show CPU affinity information then exit.*/ + if (query) { + /* When query mode and neither "live", "config" nor "current" + * is specified, set VIR_DOMAIN_AFFECT_CURRENT as flags */ + if (flags == -1) + flags = VIR_DOMAIN_AFFECT_CURRENT; + + cpumaps = vshMalloc(ctl, cpumaplen); + if (virDomainGetEmulatorPinInfo(dom, cpumaps, + cpumaplen, flags) >= 0) { + vshPrint(ctl, "%s %s\n", _("emulator:"), _("CPU Affinity")); + vshPrint(ctl, "----------------------------------\n"); + 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 (flags == -1) + flags = VIR_DOMAIN_AFFECT_LIVE; + + if (virDomainPinEmulator(dom, cpumap, cpumaplen, flags) != 0) + ret = false; + +cleanup: + VIR_FREE(cpumap); + virDomainFree(dom); + return ret; + +parse_error: + vshError(ctl, "%s", _("cpulist: Invalid format.")); + ret = false; + goto cleanup; +} + +/* * "setvcpus" command */ static const vshCmdInfo info_setvcpus[] = { @@ -8200,6 +8387,7 @@ const vshCmdDef domManagementCmds[] = { {"vcpucount", cmdVcpucount, opts_vcpucount, info_vcpucount, 0}, {"vcpuinfo", cmdVcpuinfo, opts_vcpuinfo, info_vcpuinfo, 0}, {"vcpupin", cmdVcpuPin, opts_vcpupin, info_vcpupin, 0}, + {"emulatorpin", cmdEmulatorPin, opts_emulatorpin, info_emulatorpin, 0}, {"vncdisplay", cmdVNCDisplay, opts_vncdisplay, info_vncdisplay, 0}, {NULL, NULL, NULL, NULL, 0} }; diff --git a/tools/virsh.pod b/tools/virsh.pod index 35613c4..ec3c331 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -1614,6 +1614,22 @@ If no flag is specified, behavior is different depending on hypervisor. B<Note>: The expression is sequentially evaluated, so "0-15,^8" is identical to "9-14,0-7,15" but not identical to "^8,0-15". +=item B<emulatorpin> I<domain> [I<cpulist>] [[I<--live>] [I<--config>] + | [I<--current>]] + +Query or change the pinning of domain's emulator threads to host physical +CPUs. + +See B<vcpupin> for I<cpulist>. + +If I<--live> is specified, affect a running guest. +If I<--config> is specified, affect the next boot of a persistent guest. +If I<--current> is specified, affect the current guest state. +Both I<--live> and I<--config> flags may be given if I<cpulist> is present, +but I<--current> is exclusive. +If no flag is specified, behavior is different depending on hypervisor. + + =item B<vncdisplay> I<domain> Output the IP address and port number for the VNC display. If the information -- 1.7.10.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list