On 01/20/2014 08:15 PM, Thorsten Behrens wrote: > This reads blkio stats from blkio.throttle.io_service_bytes and > blkio.throttle.io_serviced. > --- > > Note on v3: > - rebased to current master, sadly the > virCgroupSetBlkioDeviceReadBps etc conflicted > > src/libvirt_private.syms | 2 + > src/util/vircgroup.c | 242 +++++++++++++++++++++++++++++++++++++++++++++++ > src/util/vircgroup.h | 12 +++ > 3 files changed, 256 insertions(+) > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index 3ede3d5..1e44ed8 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -1002,6 +1002,8 @@ virCgroupDenyDevice; > virCgroupDenyDeviceMajor; > virCgroupDenyDevicePath; > virCgroupFree; > +virCgroupGetBlkioIoDeviceServiced; > +virCgroupGetBlkioIoServiced; > virCgroupGetBlkioWeight; > virCgroupGetCpuacctPercpuUsage; > virCgroupGetCpuacctStat; > diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c > index a6d60c5..2b70bcb 100644 > --- a/src/util/vircgroup.c > +++ b/src/util/vircgroup.c > @@ -1786,6 +1786,221 @@ 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, > + long long *bytes_write, > + long long *requests_read, > + long long *requests_write) > +{ > + char *str1 = NULL, *str2 = NULL, *str3 = NULL, *p; > + struct stat sb; > + 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 > + }; > + > + 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; > + > + if (!(p = strstr(str1, str3))) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Cannot find byte stats for block device '%s'"), > + p); path? > + goto cleanup; > + } > + > + if (!(p = strstr(str2, str3))) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Cannot find request stats for block device '%s'"), > + p); here too; > + goto cleanup; > + } > + > + for (i = 0; i < ARRAY_CARDINALITY(value_names); i++) { > + 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])); p may null here. > + 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])); here too; ACK with these changed. -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list