This patch adds --query option to "virsh vcpupin" command. Its feature is to show CPU affnity information in more reader-friendly way. # virsh vcpupin VM --query --config VCPU: CPU Affinity ---------------------------------- 0: 1-6,9-20 1: 10 2: 5,9-11,15-20 3: 1,3,5,7,9,11,13,15 When --query is specified, cpulist is not required and vcpu number is optional. When vcpu number is provided, information of only specified vcpu is displayed. Signed-off-by: Taku Izumi <izumi.taku@xxxxxxxxxxxxxx> --- tools/virsh.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++-------- tools/virsh.pod | 11 +++++- 2 files changed, 93 insertions(+), 15 deletions(-) Index: libvirt/tools/virsh.c =================================================================== --- libvirt.orig/tools/virsh.c +++ libvirt/tools/virsh.c @@ -2992,15 +2992,16 @@ cmdVcpuinfo(vshControl *ctl, const vshCm * "vcpupin" command */ static const vshCmdInfo info_vcpupin[] = { - {"help", N_("control domain vcpu affinity")}, + {"help", N_("control or query domain vcpu affinity")}, {"desc", N_("Pin domain VCPUs to host physical CPUs.")}, {NULL, NULL} }; static const vshCmdOptDef opts_vcpupin[] = { {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, - {"vcpu", VSH_OT_INT, VSH_OFLAG_REQ, N_("vcpu number")}, - {"cpulist", VSH_OT_DATA, VSH_OFLAG_REQ, N_("host cpu number(s) (comma separated)")}, + {"vcpu", VSH_OT_INT, 0, N_("vcpu number")}, + {"cpulist", VSH_OT_DATA, VSH_OFLAG_EMPTY_OK, N_("host cpu number(s)")}, + {"query", VSH_OT_BOOL, 0, N_("query CPU affinitiy information")}, {"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")}, @@ -3013,14 +3014,18 @@ cmdVcpupin(vshControl *ctl, const vshCmd virDomainInfo info; virDomainPtr dom; virNodeInfo nodeinfo; - int vcpu; + int vcpu = -1; const char *cpulist = NULL; bool ret = true; - unsigned char *cpumap; + unsigned char *cpumap = NULL; + unsigned char *cpumaps = NULL; int cpumaplen; - int i, cpu, lastcpu, maxcpu; + int bit, lastbit; + bool isInvert; + int i, cpu, lastcpu, maxcpu, ncpus; bool unuse = false; const char *cur; + int query = vshCommandOptBool(cmd, "query"); int config = vshCommandOptBool(cmd, "config"); int live = vshCommandOptBool(cmd, "live"); int current = vshCommandOptBool(cmd, "current"); @@ -3049,14 +3054,22 @@ cmdVcpupin(vshControl *ctl, const vshCmd return false; if (vshCommandOptInt(cmd, "vcpu", &vcpu) <= 0) { - vshError(ctl, "%s", _("vcpupin: Invalid or missing vCPU number.")); - virDomainFree(dom); - return false; + /* When query mode, "vcpu" is optional */ + if (!query) { + vshError(ctl, "%s", + _("vcpupin: Invalid or missing vCPU number.")); + virDomainFree(dom); + return false; + } } if (vshCommandOptString(cmd, "cpulist", &cpulist) <= 0) { - virDomainFree(dom); - return false; + /* When query mode, "cpulist" is optional */ + if (!query) { + vshError(ctl, "%s", _("vcpupin: Missing cpulist.")); + virDomainFree(dom); + return false; + } } if (virNodeGetInfo(ctl->conn, &nodeinfo) != 0) { @@ -3078,8 +3091,65 @@ cmdVcpupin(vshControl *ctl, const vshCmd maxcpu = VIR_NODEINFO_MAXCPUS(nodeinfo); cpumaplen = VIR_CPU_MAPLEN(maxcpu); - cpumap = vshCalloc(ctl, 0, cpumaplen); + /* Query mode: show CPU affinity information then exit.*/ + if (query) { + /* When query mode and neither "live", "config" nor "curent" is specified, + * set VIR_DOMAIN_AFFECT_CURRENT as flags */ + if (flags == -1) + flags = VIR_DOMAIN_AFFECT_CURRENT; + + cpumaps = vshMalloc(ctl, info.nrVirtCpu * cpumaplen); + if ((ncpus = virDomainGetVcpupinInfo(dom, info.nrVirtCpu, + cpumaps, cpumaplen, flags)) >= 0) { + + vshPrint(ctl, "%s %s\n", _("VCPU:"), _("CPU Affinity")); + vshPrint(ctl, "----------------------------------\n"); + for (i = 0; i < ncpus; i++) { + + if (vcpu != -1 && i != vcpu) + continue; + + bit = lastbit = 0; + isInvert = false; + lastcpu = -1; + + vshPrint(ctl, "%4d: ", i); + for (cpu = 0; cpu < maxcpu; cpu++) { + + if (VIR_CPU_USABLE(cpumaps, cpumaplen, i, cpu)) + bit = 1; + else + bit = 0; + + isInvert = (bit ^ lastbit) ? true : false; + if (bit && isInvert) { + if (lastcpu == -1) + vshPrint(ctl, "%d", cpu); + else + vshPrint(ctl, ",%d", cpu); + lastcpu = cpu; + } + if (!bit && isInvert && lastcpu != cpu - 1) + vshPrint(ctl, "-%d", cpu - 1); + lastbit = bit; + } + if (bit && !isInvert) { + vshPrint(ctl, "-%d", maxcpu - 1); + } + vshPrint(ctl, "\n"); + } + + } else { + ret = false; + } + VIR_FREE(cpumaps); + goto cleanup; + } + + /* Pin mode: pinning specified vcpu to specified physical cpus*/ + + cpumap = vshCalloc(ctl, 0, cpumaplen); /* Parse cpulist */ cur = cpulist; if (*cur == 0) { @@ -3161,7 +3231,8 @@ cmdVcpupin(vshControl *ctl, const vshCmd } cleanup: - VIR_FREE(cpumap); + if (cpumap) + VIR_FREE(cpumap); virDomainFree(dom); return ret; Index: libvirt/tools/virsh.pod =================================================================== --- libvirt.orig/tools/virsh.pod +++ libvirt/tools/virsh.pod @@ -838,8 +838,15 @@ vCPUs, the running time, the affinity to =item B<vcpupin> I<domain-id> I<vcpu> I<cpulist> optional I<--live> I<--config> I<--current> -Pin domain VCPUs to host physical CPUs. The I<vcpu> number must be provided -and I<cpulist> is a list of physical CPU numbers. Its syntax is a comma +=item B<vcpupin> I<domain-id> I<--query> optional I<vcpu> I<--live> I<--config> +I<--current> + +Pin domain VCPUs to host physical CPUs, or query CPU affinity information +(specify I<--query>). When pinning vCPU, the I<vcpu> number and I<cpulist> must +be provided. When querrying affinity information, I<cpulist> is not required +and I<vcpu> is optional. + +I<cpulist> is a list of physical CPU numbers. Its syntax is a comma separated list and a special markup using '-' and '^' (ex. '0-4', '0-3,^2') can also be allowed. The '-' denotes the range and the '^' denotes exclusive. If you want to reset vcpupin setting, that is, to pin vcpu all physical cpus, -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list