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); > -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list