[libvirt] [PATCHv3] Add util virCgroupGetBlkioIo*Serviced methods.
Gao feng
gaofeng at cn.fujitsu.com
Thu Jan 23 09:47:50 UTC 2014
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.
More information about the libvir-list
mailing list