On Tue, Aug 21, 2012 at 05:18:40PM +0800, Hu Tao wrote: > --- > 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; That test looks redundant to me as virParseNumber will do that check and return -1 if it fails. I think we can remove those 2 lines and just trust virParseNumber() , but since that check is done in cmdVcpuPin() I will let that as a later cleanup for both > + 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 ACK, looks fine Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@xxxxxxxxxxxx | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list