As documented in linux.git/Documentation/cgroups/cpuacct.txt, cpuacct.stat returns user and system time in ticks (the same unit used in times(2)). It would be a bit nicer if it were like getrusage(2) and reported timeval contents, or like cpuacct.usage and in nanoseconds, but we can't be picky. * src/util/cgroup.h (virCgroupGetCpuacctStat): New function. * src/util/cgroup.c (virCgroupGetCpuacctStat): Implement it. (virCgroupGetValueStr): Allow for multi-line files. * src/libvirt_private.syms (cgroup.h): Export it. --- src/libvirt_private.syms | 1 + src/util/cgroup.c | 51 ++++++++++++++++++++++++++++++++++++++++++++- src/util/cgroup.h | 4 ++- 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d7ec221..1f55f5d 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -78,6 +78,7 @@ virCgroupGetCpuCfsPeriod; virCgroupGetCpuCfsQuota; virCgroupGetCpuShares; virCgroupGetCpuacctPercpuUsage; +virCgroupGetCpuacctStat; virCgroupGetCpuacctUsage; virCgroupGetCpusetMems; virCgroupGetFreezerState; diff --git a/src/util/cgroup.c b/src/util/cgroup.c index c150fbb..ad49bc2 100644 --- a/src/util/cgroup.c +++ b/src/util/cgroup.c @@ -355,8 +355,8 @@ static int virCgroupGetValueStr(virCgroupPtr group, VIR_DEBUG("Failed to read %s: %m\n", keypath); } else { /* Terminated with '\n' has sometimes harmful effects to the caller */ - char *p = strchr(*value, '\n'); - if (p) *p = '\0'; + if ((*value)[rc - 1] == '\n') + (*value)[rc - 1] = '\0'; rc = 0; } @@ -1561,6 +1561,53 @@ int virCgroupGetCpuacctPercpuUsage(virCgroupPtr group, char **usage) "cpuacct.usage_percpu", usage); } +#ifdef _SC_CLK_TCK +int virCgroupGetCpuacctStat(virCgroupPtr group, unsigned long long *user, + unsigned long long *sys) +{ + char *str; + char *p; + int ret; + static double scale = -1.0; + + if ((ret = virCgroupGetValueStr(group, VIR_CGROUP_CONTROLLER_CPUACCT, + "cpuacct.stat", &str)) < 0) + return ret; + if (!(p = STRSKIP(str, "user ")) || + virStrToLong_ull(p, &p, 10, user) < 0 || + !(p = STRSKIP(p, "\nsystem ")) || + virStrToLong_ull(p, NULL, 10, sys) < 0) { + ret = -EINVAL; + goto cleanup; + } + /* times reported are in system ticks (generally 100 Hz), but that + * rate can theoretically vary between machines. Scale things + * into approximate nanoseconds. */ + if (scale < 0) { + long ticks_per_sec = sysconf(_SC_CLK_TCK); + if (ticks_per_sec == -1) { + ret = -errno; + goto cleanup; + } + scale = 1000000000.0 / ticks_per_sec; + } + *user *= scale; + *sys *= scale; + + ret = 0; +cleanup: + VIR_FREE(str); + return ret; +} +#else +int virCgroupGetCpuacctStat(virCgroupPtr group ATTRIBUTE_UNUSED, + unsigned long long *user ATTRIBUTE_UNUSED, + unsigned long long *sys ATTRIBUTE_UNUSED) +{ + return -ENOSYS; +} +#endif + int virCgroupSetFreezerState(virCgroupPtr group, const char *state) { return virCgroupSetValueStr(group, diff --git a/src/util/cgroup.h b/src/util/cgroup.h index b4e0f37..8486c42 100644 --- a/src/util/cgroup.h +++ b/src/util/cgroup.h @@ -1,7 +1,7 @@ /* * cgroup.h: Interface to tools for managing cgroups * - * Copyright (C) 2011 Red Hat, Inc. + * Copyright (C) 2011-2012 Red Hat, Inc. * Copyright IBM Corp. 2008 * * See COPYING.LIB for the License of this software @@ -116,6 +116,8 @@ int virCgroupGetCpuCfsQuota(virCgroupPtr group, long long *cfs_quota); int virCgroupGetCpuacctUsage(virCgroupPtr group, unsigned long long *usage); int virCgroupGetCpuacctPercpuUsage(virCgroupPtr group, char **usage); +int virCgroupGetCpuacctStat(virCgroupPtr group, unsigned long long *user, + unsigned long long *sys); int virCgroupSetFreezerState(virCgroupPtr group, const char *state); int virCgroupGetFreezerState(virCgroupPtr group, char **state); -- 1.7.7.6 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list