[Libvir] Here the patch for virtual CPU functions.
Daniel P. Berrange
berrange at redhat.com
Sat Aug 5 00:27:43 UTC 2006
On Fri, Aug 04, 2006 at 06:55:17PM +0100, Daniel P. Berrange wrote:
> On Fri, Aug 04, 2006 at 05:45:41AM -0400, Daniel Veillard wrote:
> > On Thu, Aug 03, 2006 at 03:32:46PM +0200, Philippe Berthault wrote:
> > I had a few things to change:
> > - discard // based comments to stick just to /*
> > - apply the header patch to libvirt.h.in not to the generated header
> > - shorten some comments to fit in 80 characters wide
> > - renamed the macros adding the VIR_ prefix to avoid potential name
> > collision with other headers
I added 3 more convenience macros:
VIR_NODEINFO_MAXCPUS(nodeinfo)
VIR_CPU_MAPLEN(cpu)
VIR_CPU_FULL_MAPLEN(vcpu, cpu)
To hide the maths from developers.
I also bug-fixed the pin cpu method which mistakenly checked for vcpu < 1
instead of vcpu < 0 when validating args.
See atached patch for these changes
> One more:
>
> - expose the new APIs via virsh. Michael originally suggsted pretty much
> following the style of 'xm vcpu-pin' and 'vcpu-list'. Seems like a fairly
> reasonable pattern to follow.
See the attached patch which adds these commands. eg:
# ~berrange/usr/bin/virsh vcpuinfo Demo03
VCPU: 0
CPU: 1
State: blocked
CPU time: 13.4s
CPU Affinity: y-
VCPU: 1
CPU: 0
State: blocked
CPU time: 5.0s
CPU Affinity: -y
# ~berrange/usr/bin/virsh vcpupin Demo03 1 0,1
# ~berrange/usr/bin/virsh vcpuinfo Demo03
VCPU: 0
CPU: 1
State: blocked
CPU time: 13.4s
CPU Affinity: -y
VCPU: 1
CPU: 1
State: blocked
CPU time: 5.0s
CPU Affinity: yy
Dan.
--
|=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=|
|=- Perl modules: http://search.cpan.org/~danberr/ -=|
|=- Projects: http://freshmeat.net/~danielpb/ -=|
|=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|
-------------- next part --------------
diff -c -r1.200 ChangeLog
*** ChangeLog 4 Aug 2006 13:36:07 -0000 1.200
--- ChangeLog 5 Aug 2006 01:17:22 -0000
***************
*** 1,3 ****
--- 1,11 ----
+ Fri Aug 4 20:19:23 EDT 2006 Daniel Berrange <berrange at redhat.com>
+
+ * src/libvirt.c: Fix off-by-one in validated VCPU number (it is
+ zero based, not one based).
+ * include/libvirt/libvirt.h: Add some convenience macros for
+ calculating neccessary CPU map lengths & total host CPUs
+ * src/virsh.c: Add 'vcpuinfo' and 'vcpumap' commands
+
Fri Aug 4 14:45:25 CEST 2006 Daniel Veillard <veillard at redhat.com>
* python/generator.py: fix the generator when handling long integers
diff -c -r1.20 libvirt.h
*** include/libvirt/libvirt.h 4 Aug 2006 10:41:05 -0000 1.20
--- include/libvirt/libvirt.h 5 Aug 2006 01:17:22 -0000
***************
*** 167,172 ****
--- 167,184 ----
unsigned int threads;/* number of threads per core */
};
+
+ /**
+ * VIR_NODEINFO_MAXCPUS:
+ * @nodeinfo: virNodeInfo instance
+ *
+ * This macro is to calculate the total number of CPUs supported
+ * but not neccessarily active in the host.
+ */
+
+
+ #define VIR_NODEINFO_MAXCPUS(nodeinfo) ((nodeinfo).nodes*(nodeinfo).sockets*(nodeinfo).cores*(nodeinfo).threads)
+
/**
* virNodeInfoPtr:
*
***************
*** 339,344 ****
--- 351,380 ----
#define VIR_UNUSE_CPU(cpumap,cpu) (cpumap[(cpu)/8] &= ~(1<<((cpu)%8)))
+ /**
+ * VIR_CPU_MAPLEN
+ * @cpu: number of physical CPUs
+ *
+ * This macro is to be used in conjonction with virDomainPinVcpu() API.
+ * It returns the length (in bytes) required to store the complete
+ * CPU map between a single virtual & all physical CPUs of a domain.
+ */
+
+ #define VIR_CPU_MAPLEN(cpu) (((cpu)+7)/8)
+
+ /**
+ * VIR_CPU_FULL_MAPLEN
+ * @vcpu: number of virtual CPUs
+ * @cpu: number of physical CPUs
+ *
+ * This macro is to be used in conjonction with virDomainPinVcpu() API.
+ * It returns the length (in bytes) required to store the complete
+ * CPU map between all virtual & physical CPUs of a domain.
+ */
+
+ #define VIR_CPU_FULL_MAPLEN(vcpu, cpu) (((cpu)+7)/8*(vcpu))
+
+
int virDomainGetVcpus (virDomainPtr domain,
virVcpuInfoPtr info,
int maxinfo,
diff -c -r1.38 libvirt.c
*** src/libvirt.c 4 Aug 2006 10:41:05 -0000 1.38
--- src/libvirt.c 5 Aug 2006 01:17:22 -0000
***************
*** 1720,1726 ****
}
if (domain->conn->flags & VIR_CONNECT_RO)
return (-1);
! if ((vcpu < 1) || (cpumap == NULL) || (maplen < 1)) {
virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
return (-1);
}
--- 1720,1726 ----
}
if (domain->conn->flags & VIR_CONNECT_RO)
return (-1);
! if ((vcpu < 0) || (cpumap == NULL) || (maplen < 1)) {
virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
return (-1);
}
diff -c -r1.32 virsh.c
*** src/virsh.c 19 Jul 2006 22:24:37 -0000 1.32
--- src/virsh.c 5 Aug 2006 01:17:23 -0000
***************
*** 207,212 ****
--- 207,213 ----
#define vshPrint(_ctl, ...) fprintf(stdout, __VA_ARGS__)
static const char *vshDomainStateToString(int state);
+ static const char *vshDomainVcpuStateToString(int state);
static int vshConnectionUsability(vshControl * ctl, virConnectPtr conn,
int showerror);
***************
*** 794,799 ****
--- 795,969 ----
}
/*
+ * "vcpuinfo" command
+ */
+ static vshCmdInfo info_vcpuinfo[] = {
+ {"syntax", "vcpuinfo <domain>"},
+ {"help", "domain vcpu information"},
+ {"desc", "Returns basic information about the domain virtual CPUs."},
+ {NULL, NULL}
+ };
+
+ static vshCmdOptDef opts_vcpuinfo[] = {
+ {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, "domain name, id or uuid"},
+ {NULL, 0, 0, NULL}
+ };
+
+ static int
+ cmdVcpuinfo(vshControl * ctl, vshCmd * cmd)
+ {
+ virDomainInfo info;
+ virDomainPtr dom;
+ virNodeInfo nodeinfo;
+ virVcpuInfoPtr cpuinfo;
+ unsigned char *cpumap;
+ int ncpus;
+ size_t cpumaplen;
+ int ret = TRUE;
+
+ if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+ return FALSE;
+
+ if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
+ return FALSE;
+
+ if (virNodeGetInfo(ctl->conn, &nodeinfo) != 0) {
+ virDomainFree(dom);
+ return FALSE;
+ }
+
+ if (virDomainGetInfo(dom, &info) != 0) {
+ virDomainFree(dom);
+ return FALSE;
+ }
+
+ cpuinfo = malloc(sizeof(virVcpuInfo)*info.nrVirtCpu);
+ cpumaplen = VIR_CPU_FULL_MAPLEN(info.nrVirtCpu, VIR_NODEINFO_MAXCPUS(nodeinfo));
+ cpumap = malloc(cpumaplen);
+
+ if ((ncpus = virDomainGetVcpus(dom,
+ cpuinfo, info.nrVirtCpu,
+ cpumap, cpumaplen)) >= 0) {
+ int n;
+ for (n = 0 ; n < ncpus ; n++) {
+ unsigned int m;
+ vshPrint(ctl, "%-15s %d\n", "VCPU:", n);
+ vshPrint(ctl, "%-15s %d\n", "CPU:", cpuinfo[n].cpu);
+ vshPrint(ctl, "%-15s %s\n", "State:",
+ vshDomainVcpuStateToString(cpuinfo[n].state));
+ if (cpuinfo[n].cpuTime != 0) {
+ double cpuUsed = cpuinfo[n].cpuTime;
+
+ cpuUsed /= 1000000000.0;
+
+ vshPrint(ctl, "%-15s %.1lfs\n", "CPU time:", cpuUsed);
+ }
+ vshPrint(ctl, "%-15s ", "CPU Affinity:");
+ for (m = 0 ; m < VIR_NODEINFO_MAXCPUS(nodeinfo) ; m++) {
+ vshPrint(ctl, "%c", VIR_CPU_USABLE(cpumap, cpumaplen, n, m) ? 'y' : '-');
+ }
+ vshPrint(ctl, "\n");
+ if (n < (ncpus - 1)) {
+ vshPrint(ctl, "\n");
+ }
+ }
+ } else {
+ ret = FALSE;
+ }
+
+ free(cpumap);
+ free(cpuinfo);
+ virDomainFree(dom);
+ return ret;
+ }
+
+ /*
+ * "vcpupin" command
+ */
+ static vshCmdInfo info_vcpupin[] = {
+ {"syntax", "vcpupin <domain>"},
+ {"help", "control domain vcpu affinity"},
+ {"desc", "Pin domain VCPUs to host physical CPUs"},
+ {NULL, NULL}
+ };
+
+ static vshCmdOptDef opts_vcpupin[] = {
+ {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, "domain name, id or uuid"},
+ {"vcpu", VSH_OT_DATA, VSH_OFLAG_REQ, "vcpu number"},
+ {"cpulist", VSH_OT_DATA, VSH_OFLAG_REQ, "host cpu number(s) (comma separated)"},
+ {NULL, 0, 0, NULL}
+ };
+
+ static int
+ cmdVcpupin(vshControl * ctl, vshCmd * cmd)
+ {
+ virDomainInfo info;
+ virDomainPtr dom;
+ virNodeInfo nodeinfo;
+ int vcpu;
+ char *cpulist;
+ int ret = TRUE;
+ int vcpufound = 0;
+ unsigned char *cpumap;
+ int cpumaplen;
+
+ if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+ return FALSE;
+
+ if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
+ return FALSE;
+
+ vcpu = vshCommandOptInt(cmd, "vcpu", &vcpufound);
+ if (!vcpufound) {
+ virDomainFree(dom);
+ return FALSE;
+ }
+
+ if (!(cpulist = vshCommandOptString(cmd, "cpulist", NULL))) {
+ virDomainFree(dom);
+ return FALSE;
+ }
+
+ if (virNodeGetInfo(ctl->conn, &nodeinfo) != 0) {
+ virDomainFree(dom);
+ return FALSE;
+ }
+
+ if (virDomainGetInfo(dom, &info) != 0) {
+ virDomainFree(dom);
+ return FALSE;
+ }
+
+ if (vcpu >= info.nrVirtCpu) {
+ virDomainFree(dom);
+ return FALSE;
+ }
+
+ cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
+ cpumap = malloc(cpumaplen);
+ memset(cpumap, 0, cpumaplen);
+
+ do {
+ unsigned int cpu = atoi(cpulist);
+
+ if (cpu < VIR_NODEINFO_MAXCPUS(nodeinfo)) {
+ VIR_USE_CPU(cpumap, cpu);
+ }
+ cpulist = index(cpulist, ',');
+ if (cpulist)
+ cpulist++;
+ } while (cpulist);
+
+ if (virDomainPinVcpu(dom, vcpu, cpumap, cpumaplen) != 0) {
+ ret = FALSE;
+ }
+
+ free(cpumap);
+ virDomainFree(dom);
+ return ret;
+ }
+
+ /*
* "nodeinfo" command
*/
static vshCmdInfo info_nodeinfo[] = {
***************
*** 1081,1086 ****
--- 1251,1258 ----
{"save", cmdSave, opts_save, info_save},
{"shutdown", cmdShutdown, opts_shutdown, info_shutdown},
{"suspend", cmdSuspend, opts_suspend, info_suspend},
+ {"vcpuinfo", cmdVcpuinfo, opts_vcpuinfo, info_vcpuinfo},
+ {"vcpupin", cmdVcpupin, opts_vcpupin, info_vcpupin},
{"version", cmdVersion, NULL, info_version},
{NULL, NULL, NULL, NULL}
};
***************
*** 1643,1648 ****
--- 1815,1836 ----
return NULL;
}
+ static const char *
+ vshDomainVcpuStateToString(int state)
+ {
+ switch (state) {
+ case VIR_VCPU_OFFLINE:
+ return "offline";
+ case VIR_VCPU_BLOCKED:
+ return "blocked";
+ case VIR_VCPU_RUNNING:
+ return "running";
+ default:
+ return "no state";
+ }
+ return NULL;
+ }
+
static int
vshConnectionUsability(vshControl * ctl, virConnectPtr conn, int showerror)
{
More information about the libvir-list
mailing list