[libvirt] [PATCH 1/6] Add util virCgroupGetBlkioIo*Serviced methods.

Gao feng gaofeng at cn.fujitsu.com
Wed Jan 15 05:34:44 UTC 2014


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);
> 




More information about the libvir-list mailing list