cpustats: collect VM user and sys times

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.
This commit is contained in:
Eric Blake 2012-03-08 17:35:59 -07:00
parent 6e0ff1d402
commit 0d0b409863
3 changed files with 53 additions and 3 deletions

View File

@ -78,6 +78,7 @@ virCgroupGetCpuCfsPeriod;
virCgroupGetCpuCfsQuota;
virCgroupGetCpuShares;
virCgroupGetCpuacctPercpuUsage;
virCgroupGetCpuacctStat;
virCgroupGetCpuacctUsage;
virCgroupGetCpusetMems;
virCgroupGetFreezerState;

View File

@ -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,

View File

@ -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);