[lxc-devel] [lxcfs/master] Fix proc_diskstats_read function

time-river on Github lxc-bot at linuxcontainers.org
Thu Aug 29 02:43:37 UTC 2019


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 1440 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190828/1f4261b3/attachment-0001.bin>
-------------- next part --------------
From 2617a6f48adb5b94fd1745c9e1613051766e8caf Mon Sep 17 00:00:00 2001
From: river <river at vvl.me>
Date: Wed, 28 Aug 2019 21:31:30 +0800
Subject: [PATCH 1/5] proc_diskstats_read: change snprintf format

THe original snprintf format is ugly, this patch make snprintf format
consistent with `/proc/diskstats` which is define `diskstats_show()`
function at block/genhd.c in linux kernel.

Signed-off-by: river <river at vvl.me>
---
 bindings.c | 18 +++++++++++-------
 bindings.h |  3 +++
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/bindings.c b/bindings.c
index 014f400..aa6d642 100644
--- a/bindings.c
+++ b/bindings.c
@@ -3322,13 +3322,14 @@ static void parse_memstat(char *memstat, unsigned long *cached,
 	}
 }
 
-static void get_blkio_io_value(char *str, unsigned major, unsigned minor, char *iotype, unsigned long *v)
+static void get_blkio_io_value(char *str, int major, int minor,
+							   char *iotype, unsigned long *v)
 {
 	char *eol;
 	char key[32];
 
 	memset(key, 0, 32);
-	snprintf(key, 32, "%u:%u %s", major, minor, iotype);
+	snprintf(key, 32, "%d:%d %s", major, minor, iotype);
 
 	size_t len = strlen(key);
 	*v = 0;
@@ -5189,7 +5190,7 @@ static int proc_uptime_read(char *buf, size_t size, off_t offset,
 static int proc_diskstats_read(char *buf, size_t size, off_t offset,
 		struct fuse_file_info *fi)
 {
-	char dev_name[72];
+	char dev_name[DISK_NAME_LEN];
 	struct fuse_context *fc = fuse_get_context();
 	struct file_info *d = (struct file_info *)fi->fh;
 	char *cg;
@@ -5205,7 +5206,7 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset,
 	size_t cache_size = d->buflen;
 	char *line = NULL;
 	size_t linelen = 0, total_len = 0, rv = 0;
-	unsigned int major = 0, minor = 0;
+	int major = 0, minor = 0;
 	int i = 0;
 	FILE *f = NULL;
 
@@ -5278,9 +5279,12 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset,
 
 		memset(lbuf, 0, 256);
 		if (read || write || read_merged || write_merged || read_sectors || write_sectors || read_ticks || write_ticks)
-			snprintf(lbuf, 256, "%u       %u %s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
-				major, minor, dev_name, read, read_merged, read_sectors, read_ticks,
-				write, write_merged, write_sectors, write_ticks, ios_pgr, tot_ticks, rq_ticks);
+			snprintf(lbuf, 256, "%4d %7d %s %lu %lu %lu "
+					 "%lu %lu %lu %lu %lu %lu %lu %lu\n",
+					 major, minor, dev_name,
+					 read, read_merged, read_sectors, read_ticks,
+					 write, write_merged, write_sectors, write_ticks,
+					 ios_pgr, tot_ticks, rq_ticks);
 		else
 			continue;
 
diff --git a/bindings.h b/bindings.h
index fdda207..61b80fe 100644
--- a/bindings.h
+++ b/bindings.h
@@ -14,6 +14,9 @@
 /* Reserve buffer size to account for file size changes. */
 #define BUF_RESERVE_SIZE 512
 
+/* Maximun length of device name */
+#define DISK_NAME_LEN 32
+
 enum lxcfs_virt_t {
 	LXC_TYPE_CGDIR,
 	LXC_TYPE_CGFILE,

From cbea94ae42cf56f25eed8e6239d367dec82fa6ac Mon Sep 17 00:00:00 2001
From: river <river at vvl.me>
Date: Wed, 28 Aug 2019 21:54:35 +0800
Subject: [PATCH 2/5] proc_diskstats_read: get device name from sysfs

The file uevent stores device information which path is
`/sys/dev/<device type>/<major:minor>/uevent`. For example:

```
$ cat /sys/dev/block/8:0/uevent
MAJOR=8
MINOR=0
DEVNAME=sda
DEVTYPE=disk
```

Get device name from uevent instead of `/proc/diskstats`.

Signed-off-by: river <river at vvl.me>
---
 bindings.c | 160 ++++++++++++++++++++++++++++++-----------------------
 1 file changed, 92 insertions(+), 68 deletions(-)

diff --git a/bindings.c b/bindings.c
index aa6d642..4e2dff6 100644
--- a/bindings.c
+++ b/bindings.c
@@ -3322,6 +3322,45 @@ static void parse_memstat(char *memstat, unsigned long *cached,
 	}
 }
 
+static bool get_blk_device_name(unsigned int major, unsigned int minor,
+								char *device, size_t n)
+{
+	char path[PATH_MAX] = {0}, name[DISK_NAME_LEN] = {0};
+	char *line = NULL;
+	FILE *file = NULL;
+	bool retval = false;
+	size_t len = 0;
+
+	len = snprintf(path, sizeof(path),
+			"/sys/dev/block/%u:%u/uevent", major, minor);
+	if (len < 0) {
+		lxcfs_error("Internal error: path is too long\n");
+		goto out;
+	}
+
+	file = fopen(path, "r");
+	if (file == NULL) {
+		lxcfs_error("Error opening '%s': %s\n", path, strerror(errno));
+		goto out;
+	}
+
+	len = 0;
+	while (getline(&line, &len, file) != -1) {
+		if (sscanf(line, "DEVNAME=%s", name) != 1)
+			continue;
+
+		snprintf(device, n, "%s", name);
+		retval = true;
+		break;
+	}
+
+	free(line);
+	fclose(file);
+
+out:
+	return retval;
+}
+
 static void get_blkio_io_value(char *str, int major, int minor,
 							   char *iotype, unsigned long *v)
 {
@@ -5204,11 +5243,10 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset,
 	unsigned long rd_svctm = 0, wr_svctm = 0, rd_wait = 0, wr_wait = 0;
 	char *cache = d->buf;
 	size_t cache_size = d->buflen;
-	char *line = NULL;
-	size_t linelen = 0, total_len = 0, rv = 0;
+	size_t total_len = 0, rv = 0;
 	int major = 0, minor = 0;
-	int i = 0;
-	FILE *f = NULL;
+	ssize_t l = 0;
+	char lbuf[256] = {0};
 
 	if (offset){
 		if (offset > d->size)
@@ -5231,6 +5269,12 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset,
 
 	if (!cgfs_get_value("blkio", cg, "blkio.io_serviced_recursive", &io_serviced_str))
 		goto err;
+
+	if (sscanf(io_serviced_str, "%d:%d", &major, &minor) != 2)
+		goto err;
+	if (!get_blk_device_name(major, minor, dev_name, sizeof(dev_name)))
+		goto err;
+
 	if (!cgfs_get_value("blkio", cg, "blkio.io_merged_recursive", &io_merged_str))
 		goto err;
 	if (!cgfs_get_value("blkio", cg, "blkio.io_service_bytes_recursive", &io_service_bytes_str))
@@ -5240,69 +5284,51 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset,
 	if (!cgfs_get_value("blkio", cg, "blkio.io_service_time_recursive", &io_service_time_str))
 		goto err;
 
-
-	f = fopen("/proc/diskstats", "r");
-	if (!f)
+	get_blkio_io_value(io_serviced_str, major, minor, "Read", &read);
+	get_blkio_io_value(io_serviced_str, major, minor, "Write", &write);
+	get_blkio_io_value(io_merged_str, major, minor, "Read", &read_merged);
+	get_blkio_io_value(io_merged_str, major, minor, "Write", &write_merged);
+	get_blkio_io_value(io_service_bytes_str, major, minor, "Read", &read_sectors);
+	read_sectors = read_sectors/512;
+	get_blkio_io_value(io_service_bytes_str, major, minor, "Write", &write_sectors);
+	write_sectors = write_sectors/512;
+
+	get_blkio_io_value(io_service_time_str, major, minor, "Read", &rd_svctm);
+	rd_svctm = rd_svctm/1000000;
+	get_blkio_io_value(io_wait_time_str, major, minor, "Read", &rd_wait);
+	rd_wait = rd_wait/1000000;
+	read_ticks = rd_svctm + rd_wait;
+
+	get_blkio_io_value(io_service_time_str, major, minor, "Write", &wr_svctm);
+	wr_svctm =  wr_svctm/1000000;
+	get_blkio_io_value(io_wait_time_str, major, minor, "Write", &wr_wait);
+	wr_wait =  wr_wait/1000000;
+	write_ticks = wr_svctm + wr_wait;
+
+	get_blkio_io_value(io_service_time_str, major, minor, "Total", &tot_ticks);
+	tot_ticks =  tot_ticks/1000000;
+
+	snprintf(lbuf, 256, "%4d %7d %s %lu %lu %lu "
+			 "%lu %lu %lu %lu %lu %lu %lu %lu\n",
+			 major, minor, dev_name,
+			 read, read_merged, read_sectors, read_ticks,
+			 write, write_merged, write_sectors, write_ticks,
+			 ios_pgr, tot_ticks, rq_ticks);
+
+	l = snprintf(cache, cache_size, "%s", lbuf);
+	if (l < 0) {
+		perror("Error writing to fuse buf");
+		rv = 0;
 		goto err;
-
-	while (getline(&line, &linelen, f) != -1) {
-		ssize_t l;
-		char lbuf[256];
-
-		i = sscanf(line, "%u %u %71s", &major, &minor, dev_name);
-		if (i != 3)
-			continue;
-
-		get_blkio_io_value(io_serviced_str, major, minor, "Read", &read);
-		get_blkio_io_value(io_serviced_str, major, minor, "Write", &write);
-		get_blkio_io_value(io_merged_str, major, minor, "Read", &read_merged);
-		get_blkio_io_value(io_merged_str, major, minor, "Write", &write_merged);
-		get_blkio_io_value(io_service_bytes_str, major, minor, "Read", &read_sectors);
-		read_sectors = read_sectors/512;
-		get_blkio_io_value(io_service_bytes_str, major, minor, "Write", &write_sectors);
-		write_sectors = write_sectors/512;
-
-		get_blkio_io_value(io_service_time_str, major, minor, "Read", &rd_svctm);
-		rd_svctm = rd_svctm/1000000;
-		get_blkio_io_value(io_wait_time_str, major, minor, "Read", &rd_wait);
-		rd_wait = rd_wait/1000000;
-		read_ticks = rd_svctm + rd_wait;
-
-		get_blkio_io_value(io_service_time_str, major, minor, "Write", &wr_svctm);
-		wr_svctm =  wr_svctm/1000000;
-		get_blkio_io_value(io_wait_time_str, major, minor, "Write", &wr_wait);
-		wr_wait =  wr_wait/1000000;
-		write_ticks = wr_svctm + wr_wait;
-
-		get_blkio_io_value(io_service_time_str, major, minor, "Total", &tot_ticks);
-		tot_ticks =  tot_ticks/1000000;
-
-		memset(lbuf, 0, 256);
-		if (read || write || read_merged || write_merged || read_sectors || write_sectors || read_ticks || write_ticks)
-			snprintf(lbuf, 256, "%4d %7d %s %lu %lu %lu "
-					 "%lu %lu %lu %lu %lu %lu %lu %lu\n",
-					 major, minor, dev_name,
-					 read, read_merged, read_sectors, read_ticks,
-					 write, write_merged, write_sectors, write_ticks,
-					 ios_pgr, tot_ticks, rq_ticks);
-		else
-			continue;
-
-		l = snprintf(cache, cache_size, "%s", lbuf);
-		if (l < 0) {
-			perror("Error writing to fuse buf");
-			rv = 0;
-			goto err;
-		}
-		if (l >= cache_size) {
-			lxcfs_error("%s\n", "Internal error: truncated write to cache.");
-			rv = 0;
-			goto err;
-		}
-		cache += l;
-		cache_size -= l;
-		total_len += l;
 	}
+	if (l >= cache_size) {
+		lxcfs_error("%s\n", "Internal error: truncated write to cache.");
+		rv = 0;
+		goto err;
+	}
+	cache += l;
+	cache_size -= l;
+	total_len += l;
 
 	d->cached = 1;
 	d->size = total_len;
@@ -5310,11 +5336,9 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset,
 	memcpy(buf, d->buf, total_len);
 
 	rv = total_len;
+
 err:
 	free(cg);
-	if (f)
-		fclose(f);
-	free(line);
 	free(io_serviced_str);
 	free(io_merged_str);
 	free(io_service_bytes_str);

From 58567ce3b2c1fc207542184a79968dba99c45661 Mon Sep 17 00:00:00 2001
From: river <river at vvl.me>
Date: Wed, 28 Aug 2019 22:07:59 +0800
Subject: [PATCH 3/5] proc_diskstats_read: get sector size from sysfs

Signed-off-by: river <river at vvl.me>
---
 bindings.c | 36 ++++++++++++++++++++++++++++++++++--
 1 file changed, 34 insertions(+), 2 deletions(-)

diff --git a/bindings.c b/bindings.c
index 4e2dff6..6dfc1ee 100644
--- a/bindings.c
+++ b/bindings.c
@@ -3322,6 +3322,35 @@ static void parse_memstat(char *memstat, unsigned long *cached,
 	}
 }
 
+static bool get_blk_sector_size(unsigned int major, unsigned int minor,
+					int *sector_size)
+{
+	char path[PATH_MAX] = {0};
+	FILE *file;
+	size_t len;
+	bool retval = false;
+
+	len = snprintf(path, sizeof(path),
+			"/sys/dev/block/%u:%u/queue/hw_sector_size", major, minor);
+	if (len < 0) {
+		lxcfs_error("Internal error: path is too long\n");
+		goto out;
+	}
+
+	file = fopen(path, "r");
+	if (file == NULL) {
+		lxcfs_error("Error opening '%s': %s\n", path, strerror(errno));
+		goto out;
+	}
+
+	if (fscanf(file, "%d", sector_size) == 1)
+		retval = true;
+
+	fclose(file);
+out:
+	return retval;
+}
+
 static bool get_blk_device_name(unsigned int major, unsigned int minor,
 								char *device, size_t n)
 {
@@ -5230,6 +5259,7 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset,
 		struct fuse_file_info *fi)
 {
 	char dev_name[DISK_NAME_LEN];
+	int sector_size = 512;
 	struct fuse_context *fc = fuse_get_context();
 	struct file_info *d = (struct file_info *)fi->fh;
 	char *cg;
@@ -5274,6 +5304,8 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset,
 		goto err;
 	if (!get_blk_device_name(major, minor, dev_name, sizeof(dev_name)))
 		goto err;
+	if (!get_blk_sector_size(major, minor, &sector_size))
+		goto err;
 
 	if (!cgfs_get_value("blkio", cg, "blkio.io_merged_recursive", &io_merged_str))
 		goto err;
@@ -5289,9 +5321,9 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset,
 	get_blkio_io_value(io_merged_str, major, minor, "Read", &read_merged);
 	get_blkio_io_value(io_merged_str, major, minor, "Write", &write_merged);
 	get_blkio_io_value(io_service_bytes_str, major, minor, "Read", &read_sectors);
-	read_sectors = read_sectors/512;
+	read_sectors = read_sectors / sector_size;
 	get_blkio_io_value(io_service_bytes_str, major, minor, "Write", &write_sectors);
-	write_sectors = write_sectors/512;
+	write_sectors = write_sectors / sector_size;
 
 	get_blkio_io_value(io_service_time_str, major, minor, "Read", &rd_svctm);
 	rd_svctm = rd_svctm/1000000;

From 64bbd57eabf921cb6942140de6806b7488c656ba Mon Sep 17 00:00:00 2001
From: river <river at vvl.me>
Date: Wed, 28 Aug 2019 22:32:36 +0800
Subject: [PATCH 4/5] proc_diskstats_read: obtain data from 'blkio.throttle.*'

There are many scheduler in linux kernel, such as cfq, bfq, mq-deadline,
etc. However, 'blkio.[a-z_]+' is for cfq, there is nothing provided when
OS uses other scheduler.

Cgroup block controller throttle works at generic block layer which
could collect serviced and serviced_bytes information for every
scheduler.

According to Linux doc, 'blkio.*_recursive' show the same information as
their non-recursive counterparts but include stats from all the
descendant cgroups.

Signed-off-by: river <river at vvl.me>
---
 bindings.c | 112 ++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 89 insertions(+), 23 deletions(-)

diff --git a/bindings.c b/bindings.c
index 6dfc1ee..60c0c9c 100644
--- a/bindings.c
+++ b/bindings.c
@@ -3322,6 +3322,62 @@ static void parse_memstat(char *memstat, unsigned long *cached,
 	}
 }
 
+static bool get_blk_sched_name(unsigned int major, unsigned int minor,
+				char *scheduler, size_t n)
+{
+	char path[PATH_MAX] = {0};
+	char *line = NULL, *alpha;
+	size_t len = 0, i = 0;
+	FILE *file = NULL;
+	bool retval = false;
+
+	len = snprintf(path, sizeof(path),
+			"/sys/dev/block/%u:%u/queue/scheduler", major, minor);
+	if (len < 0) {
+		lxcfs_error("Internal error: path is too long\n");
+		goto out;
+	}
+
+	file = fopen(path, "r");
+	if (file == NULL) {
+		lxcfs_error("Error opening '%s': %s\n", path, strerror(errno));
+		goto out;
+	}
+
+	len = 0;
+	if ((getline(&line, &len, file)) != -1) {
+		if ((alpha = strstr(line, "[")) == NULL) {
+			lxcfs_error("Internal error: "
+						"couldn't find scheduler name from '%s'\n", line);
+			goto error;
+		}
+
+		i = 0;
+		alpha += 1;
+		while (i < n-1 && *alpha != '\0' && *alpha != ']') {
+			scheduler[i] = *alpha;
+			alpha += 1;
+			i += 1;
+		}
+		if (i < n-1 && *alpha != '\0') {
+			scheduler[i] = '\0';
+			retval = true;
+		} else if (i == n-1) {
+			lxcfs_error("Internal error: "
+						"cloudn't store scheduler name, buffer is full.\n");
+		} else {
+			lxcfs_error("Internal error: "
+						"couldn't find scheduler name from '%s'\n", line);
+		}
+	}
+
+error:
+	free(line);
+	fclose(file);
+out:
+	return retval;
+}
+
 static bool get_blk_sector_size(unsigned int major, unsigned int minor,
 					int *sector_size)
 {
@@ -5260,6 +5316,7 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset,
 {
 	char dev_name[DISK_NAME_LEN];
 	int sector_size = 512;
+	char scheduler[64] = {0};
 	struct fuse_context *fc = fuse_get_context();
 	struct file_info *d = (struct file_info *)fi->fh;
 	char *cg;
@@ -5297,7 +5354,13 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset,
 		return read_file("/proc/diskstats", buf, size, d);
 	prune_init_slice(cg);
 
-	if (!cgfs_get_value("blkio", cg, "blkio.io_serviced_recursive", &io_serviced_str))
+	if (!cgfs_get_value("blkio", cg,
+						"blkio.throttle.io_serviced_recursive",
+						&io_serviced_str))
+		goto err;
+	if (!cgfs_get_value("blkio", cg,
+						"blkio.throttle.io_service_bytes_recursive",
+						&io_service_bytes_str))
 		goto err;
 
 	if (sscanf(io_serviced_str, "%d:%d", &major, &minor) != 2)
@@ -5306,39 +5369,42 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset,
 		goto err;
 	if (!get_blk_sector_size(major, minor, &sector_size))
 		goto err;
-
-	if (!cgfs_get_value("blkio", cg, "blkio.io_merged_recursive", &io_merged_str))
-		goto err;
-	if (!cgfs_get_value("blkio", cg, "blkio.io_service_bytes_recursive", &io_service_bytes_str))
-		goto err;
-	if (!cgfs_get_value("blkio", cg, "blkio.io_wait_time_recursive", &io_wait_time_str))
-		goto err;
-	if (!cgfs_get_value("blkio", cg, "blkio.io_service_time_recursive", &io_service_time_str))
+	if (!get_blk_sched_name(major, minor, scheduler, sizeof(scheduler)))
 		goto err;
 
 	get_blkio_io_value(io_serviced_str, major, minor, "Read", &read);
 	get_blkio_io_value(io_serviced_str, major, minor, "Write", &write);
-	get_blkio_io_value(io_merged_str, major, minor, "Read", &read_merged);
-	get_blkio_io_value(io_merged_str, major, minor, "Write", &write_merged);
 	get_blkio_io_value(io_service_bytes_str, major, minor, "Read", &read_sectors);
 	read_sectors = read_sectors / sector_size;
 	get_blkio_io_value(io_service_bytes_str, major, minor, "Write", &write_sectors);
 	write_sectors = write_sectors / sector_size;
 
-	get_blkio_io_value(io_service_time_str, major, minor, "Read", &rd_svctm);
-	rd_svctm = rd_svctm/1000000;
-	get_blkio_io_value(io_wait_time_str, major, minor, "Read", &rd_wait);
-	rd_wait = rd_wait/1000000;
-	read_ticks = rd_svctm + rd_wait;
+	if (strcmp(scheduler, "cfq") == 0) {
+		if (!cgfs_get_value("blkio", cg, "blkio.io_merged_recursive", &io_merged_str))
+			goto err;
+		if (!cgfs_get_value("blkio", cg, "blkio.io_wait_time_recursive", &io_wait_time_str))
+			goto err;
+		if (!cgfs_get_value("blkio", cg, "blkio.io_service_time_recursive", &io_service_time_str))
+			goto err;
+
+		get_blkio_io_value(io_merged_str, major, minor, "Read", &read_merged);
+		get_blkio_io_value(io_merged_str, major, minor, "Write", &write_merged);
 
-	get_blkio_io_value(io_service_time_str, major, minor, "Write", &wr_svctm);
-	wr_svctm =  wr_svctm/1000000;
-	get_blkio_io_value(io_wait_time_str, major, minor, "Write", &wr_wait);
-	wr_wait =  wr_wait/1000000;
-	write_ticks = wr_svctm + wr_wait;
+		get_blkio_io_value(io_service_time_str, major, minor, "Read", &rd_svctm);
+		rd_svctm = rd_svctm/1000000;
+		get_blkio_io_value(io_wait_time_str, major, minor, "Read", &rd_wait);
+		rd_wait = rd_wait/1000000;
+		read_ticks = rd_svctm + rd_wait;
 
-	get_blkio_io_value(io_service_time_str, major, minor, "Total", &tot_ticks);
-	tot_ticks =  tot_ticks/1000000;
+		get_blkio_io_value(io_service_time_str, major, minor, "Write", &wr_svctm);
+		wr_svctm =  wr_svctm/1000000;
+		get_blkio_io_value(io_wait_time_str, major, minor, "Write", &wr_wait);
+		wr_wait =  wr_wait/1000000;
+		write_ticks = wr_svctm + wr_wait;
+
+		get_blkio_io_value(io_service_time_str, major, minor, "Total", &tot_ticks);
+		tot_ticks =  tot_ticks/1000000;
+	}
 
 	snprintf(lbuf, 256, "%4d %7d %s %lu %lu %lu "
 			 "%lu %lu %lu %lu %lu %lu %lu %lu\n",

From 0466147de0d8e131b0f988918180059f2bc3e2a3 Mon Sep 17 00:00:00 2001
From: river <river at vvl.me>
Date: Thu, 29 Aug 2019 09:40:34 +0800
Subject: [PATCH 5/5] proc_diskstats_read: improve compatibility

'blkio.throttle.*_recursive' was add in linux v4.16 (commit id:
17534c6f2c06), there is only no recursive before.

This patch is for backward compatibility.

Signed-off-by: river <river at vvl.me>
---
 bindings.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/bindings.c b/bindings.c
index 60c0c9c..b4469f1 100644
--- a/bindings.c
+++ b/bindings.c
@@ -5356,11 +5356,17 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset,
 
 	if (!cgfs_get_value("blkio", cg,
 						"blkio.throttle.io_serviced_recursive",
-						&io_serviced_str))
+						&io_serviced_str)
+		&& !cgfs_get_value("blkio", cg,
+						   "blkio.throttle.io_serviced",
+						   &io_serviced_str))
 		goto err;
 	if (!cgfs_get_value("blkio", cg,
 						"blkio.throttle.io_service_bytes_recursive",
-						&io_service_bytes_str))
+						&io_service_bytes_str)
+		&& !cgfs_get_value("blkio", cg,
+						   "blkio.throttle.io_service_bytes",
+						   &io_service_bytes_str))
 		goto err;
 
 	if (sscanf(io_serviced_str, "%d:%d", &major, &minor) != 2)


More information about the lxc-devel mailing list