[libvirt] [PATCHv5 6/6] virNodeGetCPUTimeParameters: Implement linux support
Daniel P. Berrange
berrange at redhat.com
Fri May 20 10:37:57 UTC 2011
On Tue, May 17, 2011 at 04:01:10PM +0900, Minoru Usui wrote:
> virNodeGetCPUTimeParameters: Implement linux support
>
> Signed-off-by: Minoru Usui <usui at mxm.nes.nec.co.jp>
> ---
> src/libvirt_private.syms | 1 +
> src/lxc/lxc_driver.c | 1 +
> src/nodeinfo.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++
> src/nodeinfo.h | 5 ++-
> src/qemu/qemu_driver.c | 1 +
> src/uml/uml_driver.c | 1 +
> 6 files changed, 135 insertions(+), 1 deletions(-)
>
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index acd5af3..c3c0a88 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -687,6 +687,7 @@ virNodeDeviceObjUnlock;
>
> # nodeinfo.h
> nodeCapsInitNUMA;
> +nodeGetCPUTimeParameters;
> nodeGetCellsFreeMemory;
> nodeGetFreeMemory;
> nodeGetInfo;
> diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
> index 2bb592d..4e07836 100644
> --- a/src/lxc/lxc_driver.c
> +++ b/src/lxc/lxc_driver.c
> @@ -2752,6 +2752,7 @@ static virDriver lxcDriver = {
> .domainGetSchedulerParameters = lxcGetSchedulerParameters, /* 0.5.0 */
> .domainSetSchedulerParameters = lxcSetSchedulerParameters, /* 0.5.0 */
> .domainInterfaceStats = lxcDomainInterfaceStats, /* 0.7.3 */
> + .nodeGetCPUTimeParameters = nodeGetCPUTimeParameters, /* 0.9.2 */
> .nodeGetCellsFreeMemory = nodeGetCellsFreeMemory, /* 0.6.5 */
> .nodeGetFreeMemory = nodeGetFreeMemory, /* 0.6.5 */
> .domainEventRegister = lxcDomainEventRegister, /* 0.7.0 */
> diff --git a/src/nodeinfo.c b/src/nodeinfo.c
> index f55c83e..7fdf878 100644
> --- a/src/nodeinfo.c
> +++ b/src/nodeinfo.c
> @@ -57,12 +57,19 @@
> #ifdef __linux__
> # define CPUINFO_PATH "/proc/cpuinfo"
> # define CPU_SYS_PATH "/sys/devices/system/cpu"
> +# define PROCSTAT_PATH "/proc/stat"
> +
> +#define LINUX_NB_CPU_TIME_PARAM 4
>
> /* NB, this is not static as we need to call it from the testsuite */
> int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
> virNodeInfoPtr nodeinfo,
> bool need_hyperthreads);
>
> +int linuxNodeGetCPUTimeParameters(FILE *procstat,
> + virCPUTimeParameterPtr params,
> + int *nparams);
> +
> /* Return the positive decimal contents of the given
> * CPU_SYS_PATH/cpu%u/FILE, or -1 on error. If MISSING_OK and the
> * file could not be found, return 1 instead of an error; this is
> @@ -378,6 +385,99 @@ int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
> return 0;
> }
>
> +#define TICK_TO_NSEC (1000ull * 1000ull * 1000ull / sysconf(_SC_CLK_TCK))
> +
> +int linuxNodeGetCPUTimeParameters(FILE *procstat,
> + virCPUTimeParameterPtr params,
> + int *nparams)
> +{
> + int ret = -1;
> + char line[1024];
> + unsigned long long usr, ni, sys, idle, iowait;
> + unsigned long long irq, softirq, steal, guest, guest_nice;
> +
> + if ((*nparams) == 0) {
> + /* Current number of cpu time parameters supported by linux */
> + *nparams = LINUX_NB_CPU_TIME_PARAM;
> + ret = 0;
> + goto cleanup;
> + }
> +
> + if ((*nparams) != LINUX_NB_CPU_TIME_PARAM) {
> + nodeReportError(VIR_ERR_INVALID_ARG,
> + "%s", _("Invalid parameter count"));
> + goto cleanup;
> + }
> +
> + while (fgets(line, sizeof(line), procstat) != NULL) {
> + char *buf = line;
> +
> + if (STRPREFIX(buf, "cpu ")) { /* aka total logical CPU time */
> + int i;
> +
> + if (sscanf(buf,
> + "%*s %llu %llu %llu %llu %llu" // user ~ iowait
> + "%llu %llu %llu %llu %llu", // irq ~ guest_nice
> + &usr, &ni, &sys, &idle, &iowait,
> + &irq, &softirq, &steal, &guest, &guest_nice) < 4) {
> + continue;
> + }
> +
> + for (i = 0; i < *nparams; i++) {
> + virCPUTimeParameterPtr param = ¶ms[i];
> +
> + switch (i) {
> + case 0: /* fill kernel cpu time here */
> + if (virStrcpyStatic(param->field, VIR_CPU_TIME_KERNEL)== NULL) {
> + nodeReportError(VIR_ERR_INTERNAL_ERROR,
> + "%s", _("Field kernel cpu time too long for destination"));
> + goto cleanup;
> + }
> + param->value = (sys + irq + softirq) * TICK_TO_NSEC;
> + break;
> +
> + case 1: /* fill user cpu time here */
> + if (virStrcpyStatic(param->field, VIR_CPU_TIME_USER) == NULL) {
> + nodeReportError(VIR_ERR_INTERNAL_ERROR,
> + "%s", _("Field kernel cpu time too long for destination"));
> + goto cleanup;
> + }
> + param->value = (usr + ni) * TICK_TO_NSEC;
> + break;
> +
> + case 2: /* fill idle cpu time here */
> + if (virStrcpyStatic(param->field, VIR_CPU_TIME_IDLE) == NULL) {
> + nodeReportError(VIR_ERR_INTERNAL_ERROR,
> + "%s", _("Field kernel cpu time too long for destination"));
> + goto cleanup;
> + }
> + param->value = idle * TICK_TO_NSEC;
> + break;
> +
> + case 3: /* fill iowait cpu time here */
> + if (virStrcpyStatic(param->field, VIR_CPU_TIME_IOWAIT) == NULL) {
> + nodeReportError(VIR_ERR_INTERNAL_ERROR,
> + "%s", _("Field kernel cpu time too long for destination"));
> + goto cleanup;
> + }
> + param->value = iowait * TICK_TO_NSEC;
> + break;
> +
> + default:
> + break;
> + /* should not hit here */
> + }
> + }
> + ret = 0;
> + goto cleanup;
> + }
> + }
> +
> + nodeReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no \'cpu \' line found"));
> +
> +cleanup:
> + return ret;
> +}
> #endif
>
> int nodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, virNodeInfoPtr nodeinfo) {
> @@ -416,6 +516,33 @@ int nodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, virNodeInfoPtr nodeinfo) {
> #endif
> }
>
> +int nodeGetCPUTimeParameters(virConnectPtr conn ATTRIBUTE_UNUSED,
> + virCPUTimeParameterPtr params,
> + int *nparams,
> + unsigned int flags ATTRIBUTE_UNUSED)
> +{
> +
> +#ifdef __linux__
> + {
> + int ret;
> + FILE *procstat = fopen(PROCSTAT_PATH, "r");
> + if (!procstat) {
> + virReportSystemError(errno,
> + _("cannot open %s"), PROCSTAT_PATH);
> + return -1;
> + }
> + ret = linuxNodeGetCPUTimeParameters(procstat, params, nparams);
> + VIR_FORCE_FCLOSE(procstat);
> +
> + return ret;
> + }
> +#else
> + nodeReportError(VIR_ERR_NO_SUPPORT, "%s",
> + _("node CPU time not implemented on this platform"));
> + return -1;
> +#endif
> +}
> +
> #if HAVE_NUMACTL
> # if LIBNUMA_API_VERSION <= 1
> # define NUMA_MAX_N_CPUS 4096
> diff --git a/src/nodeinfo.h b/src/nodeinfo.h
> index 88bac6c..784492c 100644
> --- a/src/nodeinfo.h
> +++ b/src/nodeinfo.h
> @@ -30,7 +30,10 @@
> int nodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo);
> int nodeCapsInitNUMA(virCapsPtr caps);
>
> -
> +int nodeGetCPUTimeParameters(virConnectPtr conn ATTRIBUTE_UNUSED,
> + virCPUTimeParameterPtr params,
> + int *nparams,
> + unsigned int flags ATTRIBUTE_UNUSED);
> int nodeGetCellsFreeMemory(virConnectPtr conn,
> unsigned long long *freeMems,
> int startCell,
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index ccaae66..579e3e4 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -7631,6 +7631,7 @@ static virDriver qemuDriver = {
> .domainBlockPeek = qemudDomainBlockPeek, /* 0.4.4 */
> .domainMemoryPeek = qemudDomainMemoryPeek, /* 0.4.4 */
> .domainGetBlockInfo = qemuDomainGetBlockInfo, /* 0.8.1 */
> + .nodeGetCPUTimeParameters = nodeGetCPUTimeParameters, /* 0.9.2 */
> .nodeGetCellsFreeMemory = nodeGetCellsFreeMemory, /* 0.4.4 */
> .nodeGetFreeMemory = nodeGetFreeMemory, /* 0.4.4 */
> .domainEventRegister = qemuDomainEventRegister, /* 0.5.0 */
> diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c
> index 536cd8c..c9138ce 100644
> --- a/src/uml/uml_driver.c
> +++ b/src/uml/uml_driver.c
> @@ -2218,6 +2218,7 @@ static virDriver umlDriver = {
> .domainGetAutostart = umlDomainGetAutostart, /* 0.5.0 */
> .domainSetAutostart = umlDomainSetAutostart, /* 0.5.0 */
> .domainBlockPeek = umlDomainBlockPeek, /* 0.5.0 */
> + .nodeGetCPUTimeParameters = nodeGetCPUTimeParameters, /* 0.9.2 */
> .nodeGetCellsFreeMemory = nodeGetCellsFreeMemory, /* 0.5.0 */
> .nodeGetFreeMemory = nodeGetFreeMemory, /* 0.5.0 */
> .isEncrypted = umlIsEncrypted, /* 0.7.3 */
ACK
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
More information about the libvir-list
mailing list