[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, §or_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, §or_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