On 01/15/2014 07:23 AM, Thorsten Behrens wrote:
This reads blkio stats from blkio.throttle.io_service_bytes and
blkio.throttle.io_serviced.
---
src/libvirt_private.syms | 2 +
src/util/vircgroup.c | 208 +++++++++++++++++++++++++++++++++++++++++++++++
src/util/vircgroup.h | 12 +++
3 files changed, 222 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 3b3de15..edbf6ba 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1003,6 +1003,8 @@ virCgroupDenyDevice;
virCgroupDenyDeviceMajor;
virCgroupDenyDevicePath;
virCgroupFree;
+virCgroupGetBlkioIoDeviceServiced;
+virCgroupGetBlkioIoServiced;
virCgroupGetBlkioWeight;
virCgroupGetCpuacctPercpuUsage;
virCgroupGetCpuacctStat;
diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
index 43eb649..1a579f0 100644
--- a/src/util/vircgroup.c
+++ b/src/util/vircgroup.c
@@ -1826,6 +1826,191 @@ virCgroupGetBlkioWeight(virCgroupPtr group, unsigned int
*weight)
/**
+ * virCgroupGetBlkioIoServiced:
+ *
+ * @group: The cgroup to get throughput for
+ * @kb: Pointer to returned serviced io in kilobytes
+ *
+ * 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;
+ int 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;
+
+ p1 = str1;
+ p2 = str2;
+
+ /* sum up all entries of the same kind, from all devices */
You only operate the first device below, you need a cycle to
operate all the devices.
+ for (i = 0; i < ARRAY_CARDINALITY(value_names); i++) {
+ if (!(p1 = strstr(p1, value_names[i])) ||
+ virStrToLong_ll(p1 + strlen(value_names[i]), &p1, 10, &stats_val)
< 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Cannot parse byte stat '%s'"),
+ p1 + strlen(value_names[i]));
had better report the value_names too.
+ goto cleanup;
+ }
+ *bytes_ptrs[i] += stats_val;
+
had better add the overflow check and report error.
+ if (!(p2 = strstr(p2, value_names[i])) ||
+ virStrToLong_ll(p2 + strlen(value_names[i]), &p2, 10, &stats_val)
< 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Cannot parse request stat '%s'"),
+ p2 + strlen(value_names[i]));
+ goto cleanup;
+ }
+ *requests_ptrs[i] += stats_val;
overflow check
+ }
+
+ 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
+ * @kb_read: Pointer to serviced read io in kilobytes
+ * @kb_write: Pointer to serviced write io in kilobytes
+ * @kb_total: Pointer to serviced io in kilobytes
+ *
+ * Returns: 0 on success, -1 on error
+ */
+int
+virCgroupGetBlkioIoDeviceServiced(virCgroupPtr group,
+ const char *path,
+ long long *bytes_read,
+ long long *bytes_write,
+ long long *requests_read,
+ long long *requests_write)
+{
+ char *str1=NULL, *str2=NULL, *str3=NULL, *p;
+ struct stat sb;
+ int 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
+ };
+
+ if (stat(path, &sb) < 0) {
+ virReportSystemError(errno,
+ _("Path '%s' is not accessible"),
+ path);
+ return -1;
+ }
+
+ if (!S_ISBLK(sb.st_mode)) {
+ virReportSystemError(EINVAL,
+ _("Path '%s' must be a block device"),
+ path);
+ return -1;
+ }
+
+ 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;
+
+ if (virAsprintf(&str3, "%d:%d ", major(sb.st_rdev), minor(sb.st_rdev))
< 0)
+ goto cleanup;
+
+ for (i = 0; i < ARRAY_CARDINALITY(value_names); i++) {
+ if (!(p = strstr(str1, str3))) {
Can you move this strstr out of cycle?
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Cannot find state for block device
'%s'"),
+ p);
+ goto cleanup;
+ }
+ if (!(p = strstr(p, value_names[i])) ||
+ virStrToLong_ll(p + strlen(value_names[i]), &p, 10, bytes_ptrs[i]) <
0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Cannot parse stat '%s'"),
+ p + strlen(value_names[i]));
+ goto cleanup;
+ }
+
+ if (!(p = strstr(str2, str3))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Cannot find state for block device
'%s'"),
+ p);
+ goto cleanup;
+ }
+ if (!(p = strstr(p, value_names[i])) ||
+ virStrToLong_ll(p + strlen(value_names[i]), &p, 10, requests_ptrs[i])
< 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Cannot parse stat '%s'"),
+ p + strlen(value_names[i]));
+ goto cleanup;
+ }
+ }
+
+ ret = 0;
+
+cleanup:
+ VIR_FREE(str3);
+ VIR_FREE(str2);
+ VIR_FREE(str1);
+ return ret;
+}
+
+
+/**
* virCgroupSetBlkioDeviceWeight:
*
* @group: The cgroup to change io device weight device for
@@ -3303,6 +3488,29 @@ virCgroupGetBlkioWeight(virCgroupPtr group ATTRIBUTE_UNUSED,
int
+virCgroupGetBlkioIoServiced(virCgroupPtr group ATTRIBUTE_UNUSED,
+ unsigned int *kb ATTRIBUTE_UNUSED)
This definition of virCgroupGetBlkioIoServiced is inconsistent.
+{
+ virReportSystemError(ENXIO, "%s",
+ _("Control groups not supported on this platform"));
+ return -1;
+}
+
+
+int
+virCgroupGetBlkioIoDeviceServiced(virCgroupPtr group ATTRIBUTE_UNUSED,
+ const char *path ATTRIBUTE_UNUSED,
+ unsigned int *kb_read ATTRIBUTE_UNUSED,
+ unsigned int *kb_write ATTRIBUTE_UNUSED,
+ unsigned int *kb_total ATTRIBUTE_UNUSED)
+{
+ virReportSystemError(ENXIO, "%s",
+ _("Control groups not supported on this platform"));
+ return -1;
+}
+
+
+int
virCgroupSetBlkioDeviceWeight(virCgroupPtr group ATTRIBUTE_UNUSED,
const char *path ATTRIBUTE_UNUSED,
unsigned int weight ATTRIBUTE_UNUSED)
diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h
index 835eb30..cd6b27b 100644
--- a/src/util/vircgroup.h
+++ b/src/util/vircgroup.h
@@ -122,6 +122,18 @@ int virCgroupMoveTask(virCgroupPtr src_group,
int virCgroupSetBlkioWeight(virCgroupPtr group, unsigned int weight);
int virCgroupGetBlkioWeight(virCgroupPtr group, unsigned int *weight);
+int virCgroupGetBlkioIoServiced(virCgroupPtr group,
+ long long *bytes_read,
+ long long *bytes_write,
+ long long *requests_read,
+ long long *requests_write);
+int virCgroupGetBlkioIoDeviceServiced(virCgroupPtr group,
+ const char *path,
+ long long *bytes_read,
+ long long *bytes_write,
+ long long *requests_read,
+ long long *requests_write);
+
int virCgroupSetBlkioDeviceWeight(virCgroupPtr group,
const char *path,
unsigned int weight);