Add util virCgroupGetBlkioIo*Serviced methods.

This reads blkio stats from blkio.throttle.io_service_bytes and
blkio.throttle.io_serviced.
This commit is contained in:
Thorsten Behrens 2014-02-14 18:48:59 +01:00 committed by Michal Privoznik
parent 6c1059ef24
commit a2bb187c7e
3 changed files with 268 additions and 0 deletions

View File

@ -1014,6 +1014,8 @@ virCgroupDenyDevice;
virCgroupDenyDeviceMajor; virCgroupDenyDeviceMajor;
virCgroupDenyDevicePath; virCgroupDenyDevicePath;
virCgroupFree; virCgroupFree;
virCgroupGetBlkioIoDeviceServiced;
virCgroupGetBlkioIoServiced;
virCgroupGetBlkioWeight; virCgroupGetBlkioWeight;
virCgroupGetCpuacctPercpuUsage; virCgroupGetCpuacctPercpuUsage;
virCgroupGetCpuacctStat; virCgroupGetCpuacctStat;

View File

@ -1785,6 +1785,233 @@ 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, *p1, *p2;
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 (!(p1 = strstr(str1, str3))) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Cannot find byte stats for block device '%s'"),
str3);
goto cleanup;
}
if (!(p2 = strstr(str2, str3))) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Cannot find request stats for block device '%s'"),
str3);
goto cleanup;
}
for (i = 0; i < ARRAY_CARDINALITY(value_names); i++) {
if (!(p1 = strstr(p1, value_names[i]))) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Cannot find byte %sstats for block device '%s'"),
value_names[i], str3);
goto cleanup;
}
if (virStrToLong_ll(p1 + strlen(value_names[i]), &p1, 10, bytes_ptrs[i]) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Cannot parse %sstat '%s'"),
value_names[i], p1 + strlen(value_names[i]));
goto cleanup;
}
if (!(p2 = strstr(p2, value_names[i]))) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Cannot find request %sstats for block device '%s'"),
value_names[i], str3);
goto cleanup;
}
if (virStrToLong_ll(p2 + strlen(value_names[i]), &p2, 10, requests_ptrs[i]) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Cannot parse %sstat '%s'"),
value_names[i], p2 + strlen(value_names[i]));
goto cleanup;
}
}
ret = 0;
cleanup:
VIR_FREE(str3);
VIR_FREE(str2);
VIR_FREE(str1);
return ret;
}
/** /**
* virCgroupSetBlkioWeight: * virCgroupSetBlkioWeight:
* *
@ -3458,6 +3685,33 @@ virCgroupMoveTask(virCgroupPtr src_group ATTRIBUTE_UNUSED,
} }
int
virCgroupGetBlkioIoServiced(virCgroupPtr group ATTRIBUTE_UNUSED,
long long *bytes_read ATTRIBUTE_UNUSED,
long long *bytes_write ATTRIBUTE_UNUSED,
long long *requests_read ATTRIBUTE_UNUSED,
long long *requests_write ATTRIBUTE_UNUSED)
{
virReportSystemError(ENXIO, "%s",
_("Control groups not supported on this platform"));
return -1;
}
int
virCgroupGetBlkioIoDeviceServiced(virCgroupPtr group ATTRIBUTE_UNUSED,
const char *path ATTRIBUTE_UNUSED,
long long *bytes_read ATTRIBUTE_UNUSED,
long long *bytes_write ATTRIBUTE_UNUSED,
long long *requests_read ATTRIBUTE_UNUSED,
long long *requests_write ATTRIBUTE_UNUSED)
{
virReportSystemError(ENXIO, "%s",
_("Control groups not supported on this platform"));
return -1;
}
int int
virCgroupSetBlkioWeight(virCgroupPtr group ATTRIBUTE_UNUSED, virCgroupSetBlkioWeight(virCgroupPtr group ATTRIBUTE_UNUSED,
unsigned int weight ATTRIBUTE_UNUSED) unsigned int weight ATTRIBUTE_UNUSED)

View File

@ -122,6 +122,18 @@ int virCgroupMoveTask(virCgroupPtr src_group,
int virCgroupSetBlkioWeight(virCgroupPtr group, unsigned int weight); int virCgroupSetBlkioWeight(virCgroupPtr group, unsigned int weight);
int virCgroupGetBlkioWeight(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, int virCgroupSetBlkioDeviceWeight(virCgroupPtr group,
const char *path, const char *path,
unsigned int weight); unsigned int weight);