]> xenbits.xensource.com Git - libvirt.git/commitdiff
Extend virCgroupGetPercpuStats to fill in vcputime too
authorJán Tomko <jtomko@redhat.com>
Thu, 3 Apr 2014 15:53:43 +0000 (17:53 +0200)
committerJán Tomko <jtomko@redhat.com>
Wed, 9 Apr 2014 14:24:08 +0000 (16:24 +0200)
Currently, virCgroupGetPercpuStats is only used by the LXC driver,
filling out the CPUTIME stats. qemuDomainGetPercpuStats does this
and also filles out VCPUTIME stats.

Extend virCgroupGetPercpuStats to also report VCPUTIME stats if
nvcpupids is non-zero. In the LXC driver, we don't have cpupids.
In the QEMU driver, there is at least one cpupid for a running domain,
so the behavior shouldn't change for QEMU either.

Also rename getSumVcpuPercpuStats to virCgroupGetPercpuVcpuSum.

src/lxc/lxc_driver.c
src/qemu/qemu_driver.c
src/util/vircgroup.c
src/util/vircgroup.h
tests/vircgrouptest.c

index 942e1392cd02a39367aebfd0788be535e77f7c7f..826d91825f592b7486b93bbc87567a0630b0ff54 100644 (file)
@@ -5658,7 +5658,7 @@ lxcDomainGetCPUStats(virDomainPtr dom,
                                               params, nparams);
     else
         ret = virCgroupGetPercpuStats(priv->cgroup, params,
-                                      nparams, start_cpu, ncpus);
+                                      nparams, start_cpu, ncpus, 0);
  cleanup:
     if (vm)
         virObjectUnlock(vm);
index d14b8926fe9d456fce0bb6cd655536e8d0cd967b..b0c6a741cb0cba4a1aa5dcc21d4cc662a695d654 100644 (file)
@@ -15964,165 +15964,6 @@ qemuDomainGetMetadata(virDomainPtr dom,
     return ret;
 }
 
-/* This function gets the sums of cpu time consumed by all vcpus.
- * For example, if there are 4 physical cpus, and 2 vcpus in a domain,
- * then for each vcpu, the cpuacct.usage_percpu looks like this:
- *   t0 t1 t2 t3
- * and we have 2 groups of such data:
- *   v\p   0   1   2   3
- *   0   t00 t01 t02 t03
- *   1   t10 t11 t12 t13
- * for each pcpu, the sum is cpu time consumed by all vcpus.
- *   s0 = t00 + t10
- *   s1 = t01 + t11
- *   s2 = t02 + t12
- *   s3 = t03 + t13
- */
-static int
-getSumVcpuPercpuStats(virCgroupPtr group,
-                      unsigned int nvcpupids,
-                      unsigned long long *sum_cpu_time,
-                      unsigned int num)
-{
-    int ret = -1;
-    size_t i;
-    char *buf = NULL;
-    virCgroupPtr group_vcpu = NULL;
-
-    for (i = 0; i < nvcpupids; i++) {
-        char *pos;
-        unsigned long long tmp;
-        size_t j;
-
-        if (virCgroupNewVcpu(group, i, false, &group_vcpu) < 0)
-            goto cleanup;
-
-        if (virCgroupGetCpuacctPercpuUsage(group_vcpu, &buf) < 0)
-            goto cleanup;
-
-        pos = buf;
-        for (j = 0; j < num; j++) {
-            if (virStrToLong_ull(pos, &pos, 10, &tmp) < 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                               _("cpuacct parse error"));
-                goto cleanup;
-            }
-            sum_cpu_time[j] += tmp;
-        }
-
-        virCgroupFree(&group_vcpu);
-        VIR_FREE(buf);
-    }
-
-    ret = 0;
- cleanup:
-    virCgroupFree(&group_vcpu);
-    VIR_FREE(buf);
-    return ret;
-}
-
-static int
-qemuDomainGetPercpuStats(virCgroupPtr group,
-                         virTypedParameterPtr params,
-                         unsigned int nparams,
-                         int start_cpu,
-                         unsigned int ncpus,
-                         unsigned int nvcpupids)
-{
-    int rv = -1;
-    size_t i;
-    int id, max_id;
-    char *pos;
-    char *buf = NULL;
-    unsigned long long *sum_cpu_time = NULL;
-    unsigned long long *sum_cpu_pos;
-    unsigned int n = 0;
-    virTypedParameterPtr ent;
-    int param_idx;
-    unsigned long long cpu_time;
-
-    /* return the number of supported params */
-    if (nparams == 0 && ncpus != 0)
-        return QEMU_NB_PER_CPU_STAT_PARAM;
-
-    /* To parse account file, we need to know how many cpus are present.  */
-    max_id = nodeGetCPUCount();
-    if (max_id < 0)
-        return rv;
-
-    if (ncpus == 0) { /* returns max cpu ID */
-        rv = max_id;
-        goto cleanup;
-    }
-
-    if (start_cpu > max_id) {
-        virReportError(VIR_ERR_INVALID_ARG,
-                       _("start_cpu %d larger than maximum of %d"),
-                       start_cpu, max_id);
-        goto cleanup;
-    }
-
-    /* we get percpu cputime accounting info. */
-    if (virCgroupGetCpuacctPercpuUsage(group, &buf))
-        goto cleanup;
-    pos = buf;
-
-    /* return percpu cputime in index 0 */
-    param_idx = 0;
-
-    /* number of cpus to compute */
-    if (start_cpu >= max_id - ncpus)
-        id = max_id - 1;
-    else
-        id = start_cpu + ncpus - 1;
-
-    for (i = 0; i <= id; i++) {
-        if (virStrToLong_ull(pos, &pos, 10, &cpu_time) < 0) {
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("cpuacct parse error"));
-            goto cleanup;
-        } else {
-            n++;
-        }
-        if (i < start_cpu)
-            continue;
-        ent = &params[(i - start_cpu) * nparams + param_idx];
-        if (virTypedParameterAssign(ent, VIR_DOMAIN_CPU_STATS_CPUTIME,
-                                    VIR_TYPED_PARAM_ULLONG, cpu_time) < 0)
-            goto cleanup;
-    }
-
-    /* return percpu vcputime in index 1 */
-    if (++param_idx >= nparams) {
-        rv = nparams;
-        goto cleanup;
-    }
-
-    if (VIR_ALLOC_N(sum_cpu_time, n) < 0)
-        goto cleanup;
-    if (getSumVcpuPercpuStats(group, nvcpupids, sum_cpu_time, n) < 0)
-        goto cleanup;
-
-    sum_cpu_pos = sum_cpu_time;
-    for (i = 0; i <= id; i++) {
-        cpu_time = *(sum_cpu_pos++);
-        if (i < start_cpu)
-            continue;
-        if (virTypedParameterAssign(&params[(i - start_cpu) * nparams +
-                                            param_idx],
-                                    VIR_DOMAIN_CPU_STATS_VCPUTIME,
-                                    VIR_TYPED_PARAM_ULLONG,
-                                    cpu_time) < 0)
-            goto cleanup;
-    }
-
-    rv = param_idx + 1;
- cleanup:
-    VIR_FREE(sum_cpu_time);
-    VIR_FREE(buf);
-    return rv;
-}
-
 
 static int
 qemuDomainGetCPUStats(virDomainPtr domain,
@@ -16164,8 +16005,8 @@ qemuDomainGetCPUStats(virDomainPtr domain,
         ret = virCgroupGetDomainTotalCpuStats(priv->cgroup,
                                               params, nparams);
     else
-        ret = qemuDomainGetPercpuStats(priv->cgroup, params, nparams,
-                                       start_cpu, ncpus, priv->nvcpupids);
+        ret = virCgroupGetPercpuStats(priv->cgroup, params, nparams,
+                                      start_cpu, ncpus, priv->nvcpupids);
  cleanup:
     if (vm)
         virObjectUnlock(vm);
index 1ff3dadb9c99eec50ab7d9a83ac6e6ae0b7aa120..7a7f52b5722b64f37f4d4f8415713caa18bcfffa 100644 (file)
@@ -2832,25 +2832,91 @@ virCgroupDenyDevicePath(virCgroupPtr group, const char *path, int perms)
 }
 
 
+/* This function gets the sums of cpu time consumed by all vcpus.
+ * For example, if there are 4 physical cpus, and 2 vcpus in a domain,
+ * then for each vcpu, the cpuacct.usage_percpu looks like this:
+ *   t0 t1 t2 t3
+ * and we have 2 groups of such data:
+ *   v\p   0   1   2   3
+ *   0   t00 t01 t02 t03
+ *   1   t10 t11 t12 t13
+ * for each pcpu, the sum is cpu time consumed by all vcpus.
+ *   s0 = t00 + t10
+ *   s1 = t01 + t11
+ *   s2 = t02 + t12
+ *   s3 = t03 + t13
+ */
+static int
+virCgroupGetPercpuVcpuSum(virCgroupPtr group,
+                          unsigned int nvcpupids,
+                          unsigned long long *sum_cpu_time,
+                          unsigned int num)
+{
+    int ret = -1;
+    size_t i;
+    char *buf = NULL;
+    virCgroupPtr group_vcpu = NULL;
+
+    for (i = 0; i < nvcpupids; i++) {
+        char *pos;
+        unsigned long long tmp;
+        size_t j;
+
+        if (virCgroupNewVcpu(group, i, false, &group_vcpu) < 0)
+            goto cleanup;
+
+        if (virCgroupGetCpuacctPercpuUsage(group_vcpu, &buf) < 0)
+            goto cleanup;
+
+        pos = buf;
+        for (j = 0; j < num; j++) {
+            if (virStrToLong_ull(pos, &pos, 10, &tmp) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("cpuacct parse error"));
+                goto cleanup;
+            }
+            sum_cpu_time[j] += tmp;
+        }
+
+        virCgroupFree(&group_vcpu);
+        VIR_FREE(buf);
+    }
+
+    ret = 0;
+ cleanup:
+    virCgroupFree(&group_vcpu);
+    VIR_FREE(buf);
+    return ret;
+}
+
+
 int
 virCgroupGetPercpuStats(virCgroupPtr group,
                         virTypedParameterPtr params,
                         unsigned int nparams,
                         int start_cpu,
-                        unsigned int ncpus)
+                        unsigned int ncpus,
+                        unsigned int nvcpupids)
 {
     int rv = -1;
     size_t i;
     int id, max_id;
     char *pos;
     char *buf = NULL;
+    unsigned long long *sum_cpu_time = NULL;
+    unsigned long long *sum_cpu_pos;
+    unsigned int n = 0;
     virTypedParameterPtr ent;
     int param_idx;
     unsigned long long cpu_time;
 
     /* return the number of supported params */
-    if (nparams == 0 && ncpus != 0)
-        return CGROUP_NB_PER_CPU_STAT_PARAM;
+    if (nparams == 0 && ncpus != 0) {
+        if (nvcpupids == 0)
+            return CGROUP_NB_PER_CPU_STAT_PARAM;
+        else
+            return CGROUP_NB_PER_CPU_STAT_PARAM + 1;
+    }
 
     /* To parse account file, we need to know how many cpus are present.  */
     max_id = nodeGetCPUCount();
@@ -2888,6 +2954,8 @@ virCgroupGetPercpuStats(virCgroupPtr group,
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                            _("cpuacct parse error"));
             goto cleanup;
+        } else {
+            n++;
         }
         if (i < start_cpu)
             continue;
@@ -2897,9 +2965,34 @@ virCgroupGetPercpuStats(virCgroupPtr group,
             goto cleanup;
     }
 
+    if (nvcpupids == 0 || param_idx + 1 >= nparams)
+        goto success;
+    /* return percpu vcputime in index 1 */
+    param_idx++;
+
+    if (VIR_ALLOC_N(sum_cpu_time, n) < 0)
+        goto cleanup;
+    if (virCgroupGetPercpuVcpuSum(group, nvcpupids, sum_cpu_time, n) < 0)
+        goto cleanup;
+
+    sum_cpu_pos = sum_cpu_time;
+    for (i = 0; i <= id; i++) {
+        cpu_time = *(sum_cpu_pos++);
+        if (i < start_cpu)
+            continue;
+        if (virTypedParameterAssign(&params[(i - start_cpu) * nparams +
+                                            param_idx],
+                                    VIR_DOMAIN_CPU_STATS_VCPUTIME,
+                                    VIR_TYPED_PARAM_ULLONG,
+                                    cpu_time) < 0)
+            goto cleanup;
+    }
+
+ success:
     rv = param_idx + 1;
 
  cleanup:
+    VIR_FREE(sum_cpu_time);
     VIR_FREE(buf);
     return rv;
 }
index ecac9a0e3676c4d956a24571998d1c5f00b9809c..7bb46bf5028583a92841a0edf1d09b168bc0e932 100644 (file)
@@ -206,7 +206,8 @@ virCgroupGetPercpuStats(virCgroupPtr group,
                         virTypedParameterPtr params,
                         unsigned int nparams,
                         int start_cpu,
-                        unsigned int ncpus);
+                        unsigned int ncpus,
+                        unsigned int nvcpupids);
 
 int
 virCgroupGetDomainTotalCpuStats(virCgroupPtr group,
index dd078c1db61b94a015f94c6cb0b7938cba10dd81..35ac0c006785af7d4ccabf7091d6e36fea1363a5 100644 (file)
@@ -560,7 +560,7 @@ static int testCgroupGetPercpuStats(const void *args ATTRIBUTE_UNUSED)
 
     if ((rv = virCgroupGetPercpuStats(cgroup,
                                       params,
-                                      2, 0, 1)) < 0) {
+                                      2, 0, 1, 0)) < 0) {
         fprintf(stderr, "Failed call to virCgroupGetPercpuStats for /virtualmachines cgroup: %d\n", -rv);
         goto cleanup;
     }