]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
cpustats: collect VM user and sys times
authorEric Blake <eblake@redhat.com>
Fri, 9 Mar 2012 00:35:59 +0000 (17:35 -0700)
committerEric Blake <eblake@redhat.com>
Mon, 12 Mar 2012 14:46:56 +0000 (08:46 -0600)
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
src/util/cgroup.c
src/util/cgroup.h

index d7ec221b630d01f265c051ed43b272e9ef4944d9..1f55f5d3fddefc55dcbf0f2454168b382dd84bbf 100644 (file)
@@ -78,6 +78,7 @@ virCgroupGetCpuCfsPeriod;
 virCgroupGetCpuCfsQuota;
 virCgroupGetCpuShares;
 virCgroupGetCpuacctPercpuUsage;
+virCgroupGetCpuacctStat;
 virCgroupGetCpuacctUsage;
 virCgroupGetCpusetMems;
 virCgroupGetFreezerState;
index c150fbb8b2b18aadb0ca35050162673761648968..ad49bc251388c2b2abbe8e37b8c4351662906ad6 100644 (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,
index b4e0f373d8b4a1b2579f704064fd06a5e49d3e1f..8486c42cb81c106d4f07d4023620c12647e41de9 100644 (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);