This reads blkio stats from blkio.throttle.io_service_bytes and
blkio.throttle.io_serviced.
---
Notes v3:
- beyond the minor nits from the last review,
virCgroupGetBlkioIoDeviceServiced was rather busted wrt. string
ptr p. Now fixed, and with unit test (separate patch)
src/libvirt_private.syms | 2 +
src/util/vircgroup.c | 254 +++
src/util/vircgroup.h | 12 +++
3 files changed, 268 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 1a8d088..5b40d73 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1005,6 +1005,8 @@ virCgroupDenyDevice;
virCgroupDenyDeviceMajor;
virCgroupDenyDevicePath;
virCgroupFree;
+virCgroupGetBlkioIoDeviceServiced;
+virCgroupGetBlkioIoServiced;
virCgroupGetBlkioWeight;
virCgroupGetCpuacctPercpuUsage;
virCgroupGetCpuacctStat;
diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
index a6d60c5..867bd26 100644
--- a/src/util/vircgroup.c
+++ b/src/util/vircgroup.c
@@ -1786,6 +1786,233 @@ virCgroupPathOfController(virCgroupPtr group,
/**
+ * virCgroupGetBlkioIoServiced:
+ *
+ * @group: The cgroup to get throughput for
+ * @bytes_read: Pointer to returned bytes read
+ * @bytes_write: Pointer to returned bytes written
+ * @requests_read: Pointer to returned read io ops
+ * @requests_write: Pointer to returned write io ops
+ *
+ * Returns: 0 on success, -1 on error
+ */
+int
+virCgroupGetBlkioIoServiced(virCgroupPtr group,
+long long *bytes_read,
+long long *bytes_write,
+long long *requests_read,
+long long *requests_write)
+{
+long long stats_val;
+char *str1 = NULL, *str2 = NULL, *p1, *p2;
+size_t i;
+int ret = -1;
+
+const char *value_names[] = {
+Read ,
+Write
+};
+long long *bytes_ptrs[] = {
+bytes_read,
+bytes_write
+};
+long long *requests_ptrs[] = {
+requests_read,
+requests_write
+};
+
+*bytes_read = 0;
+*bytes_write = 0;
+*requests_read = 0;
+*requests_write = 0;
+
+if (virCgroupGetValueStr(group,
+ VIR_CGROUP_CONTROLLER_BLKIO,
+ blkio.throttle.io_service_bytes, str1) 0)
+goto cleanup;
+
+if (virCgroupGetValueStr(group,
+ VIR_CGROUP_CONTROLLER_BLKIO,
+ blkio.throttle.io_serviced, str2) 0)
+goto cleanup;
+
+/* sum up all entries of the same kind, from all devices */
+for (i = 0; i ARRAY_CARDINALITY(value_names); i++) {
+p1 = str1;
+p2 = str2;
+
+while ((p1 = strstr(p1, value_names[i]))) {
+p1 += strlen(value_names[i]);
+if (virStrToLong_ll(p1, p1, 10, stats_val) 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+ _(Cannot parse byte %sstat '%s'),
+ value_names[i],
+ p1);
+goto cleanup;
+}
+
+if (stats_val 0 ||
+(stats_val 0 *bytes_ptrs[i] (LLONG_MAX - stats_val)))
+{
+virReportError(VIR_ERR_OVERFLOW,
+ _(Sum of byte %sstat overflows),
+ value_names[i]);
+goto cleanup;
+}
+*bytes_ptrs[i] += stats_val;
+}
+
+while ((p2 = strstr(p2, value_names[i]))) {
+p2 += strlen(value_names[i]);
+if (virStrToLong_ll(p2, p2, 10, stats_val) 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+ _(Cannot parse %srequest stat '%s'),
+ value_names[i],
+ p2);
+goto cleanup;
+}
+
+if (stats_val 0 ||
+(stats_val 0 *requests_ptrs[i] (LLONG_MAX - stats_val)))
+{
+virReportError(VIR_ERR_OVERFLOW,
+ _(Sum of %srequest stat overflows),
+ value_names[i]);
+goto cleanup;
+}
+*requests_ptrs[i] += stats_val;
+}
+}
+
+ret = 0;
+
+cleanup:
+VIR_FREE(str2);
+VIR_FREE(str1);
+return ret;
+}
+
+
+/**
+ * virCgroupGetBlkioIoDeviceServiced:
+ *
+ * @group: The cgroup to get throughput for
+ * @path: The device to get throughput for
+ * @bytes_read: Pointer to returned bytes read
+ * @bytes_write: Pointer to returned bytes written
+ * @requests_read: Pointer to returned read io ops
+ * @requests_write: Pointer to returned write io ops
+ *
+ * Returns: 0 on success, -1 on error
+ */
+int
+virCgroupGetBlkioIoDeviceServiced(virCgroupPtr group,
+ const char *path,
+ long long *bytes_read,