return 0;
}
+const uint64_t cgroup_io_limit_defaults[_CGROUP_IO_LIMIT_TYPE_MAX] = {
+ [CGROUP_IO_RBPS_MAX] = CGROUP_LIMIT_MAX,
+ [CGROUP_IO_WBPS_MAX] = CGROUP_LIMIT_MAX,
+};
+
+static const char* const cgroup_io_limit_type_table[_CGROUP_IO_LIMIT_TYPE_MAX] = {
+ [CGROUP_IO_RBPS_MAX] = "IOReadBandwidthMax",
+ [CGROUP_IO_WBPS_MAX] = "IOWriteBandwidthMax",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(cgroup_io_limit_type, CGroupIOLimitType);
+
int cg_cpu_shares_parse(const char *s, uint64_t *ret) {
uint64_t u;
int r;
(x >= CGROUP_WEIGHT_MIN && x <= CGROUP_WEIGHT_MAX);
}
+/* IO limits on unified hierarchy */
+typedef enum CGroupIOLimitType {
+ CGROUP_IO_RBPS_MAX,
+ CGROUP_IO_WBPS_MAX,
+
+ _CGROUP_IO_LIMIT_TYPE_MAX,
+ _CGROUP_IO_LIMIT_TYPE_INVALID = -1
+} CGroupIOLimitType;
+
+extern const uint64_t cgroup_io_limit_defaults[_CGROUP_IO_LIMIT_TYPE_MAX];
+
+const char* cgroup_io_limit_type_to_string(CGroupIOLimitType t) _const_;
+CGroupIOLimitType cgroup_io_limit_type_from_string(const char *s) _pure_;
+
/* Special values for the cpu.shares attribute */
#define CGROUP_CPU_SHARES_INVALID ((uint64_t) -1)
#define CGROUP_CPU_SHARES_MIN UINT64_C(2)
LIST_FOREACH(device_limits, il, c->io_device_limits) {
char buf[FORMAT_BYTES_MAX];
-
- if (il->rbps_max != CGROUP_LIMIT_MAX)
- fprintf(f,
- "%sIOReadBandwidthMax=%s %s\n",
- prefix,
- il->path,
- format_bytes(buf, sizeof(buf), il->rbps_max));
-
- if (il->wbps_max != CGROUP_LIMIT_MAX)
- fprintf(f,
- "%sIOWriteBandwidthMax=%s %s\n",
- prefix,
- il->path,
- format_bytes(buf, sizeof(buf), il->wbps_max));
+ CGroupIOLimitType type;
+
+ for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
+ if (il->limits[type] != cgroup_io_limit_defaults[type])
+ fprintf(f,
+ "%s%s=%s %s\n",
+ prefix,
+ cgroup_io_limit_type_to_string(type),
+ il->path,
+ format_bytes(buf, sizeof(buf), il->limits[type]));
}
LIST_FOREACH(device_weights, w, c->blockio_device_weights)
}
LIST_FOREACH_SAFE(device_limits, l, next, c->io_device_limits) {
- char rbps_buf[DECIMAL_STR_MAX(uint64_t)] = "max";
- char wbps_buf[DECIMAL_STR_MAX(uint64_t)] = "max";
+ char limit_bufs[_CGROUP_IO_LIMIT_TYPE_MAX][DECIMAL_STR_MAX(uint64_t)];
char buf[DECIMAL_STR_MAX(dev_t)*2+2+(5+DECIMAL_STR_MAX(uint64_t)+1)*2];
+ CGroupIOLimitType type;
dev_t dev;
unsigned n = 0;
if (r < 0)
continue;
- if (l->rbps_max != CGROUP_LIMIT_MAX) {
- xsprintf(rbps_buf, "%" PRIu64, l->rbps_max);
- n++;
- }
-
- if (l->wbps_max != CGROUP_LIMIT_MAX) {
- xsprintf(wbps_buf, "%" PRIu64, l->wbps_max);
- n++;
+ for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++) {
+ if (l->limits[type] != cgroup_io_limit_defaults[type]) {
+ xsprintf(limit_bufs[type], "%" PRIu64, l->limits[type]);
+ n++;
+ } else {
+ xsprintf(limit_bufs[type], "%s",
+ l->limits[type] == CGROUP_LIMIT_MAX ? "max" : "0");
+ }
}
- xsprintf(buf, "%u:%u rbps=%s wbps=%s\n", major(dev), minor(dev), rbps_buf, wbps_buf);
+ xsprintf(buf, "%u:%u rbps=%s wbps=%s\n", major(dev), minor(dev),
+ limit_bufs[CGROUP_IO_RBPS_MAX], limit_bufs[CGROUP_IO_WBPS_MAX]);
r = cg_set_attribute("io", path, "io.max", buf);
if (r < 0)
log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
#include "list.h"
#include "time-util.h"
+#include "cgroup-util.h"
typedef struct CGroupContext CGroupContext;
typedef struct CGroupDeviceAllow CGroupDeviceAllow;
struct CGroupIODeviceLimit {
LIST_FIELDS(CGroupIODeviceLimit, device_limits);
char *path;
- uint64_t rbps_max;
- uint64_t wbps_max;
+ uint64_t limits[_CGROUP_IO_LIMIT_TYPE_MAX];
};
struct CGroupBlockIODeviceWeight {
return r;
LIST_FOREACH(device_limits, l, c->io_device_limits) {
- uint64_t v;
+ CGroupIOLimitType type;
- if (streq(property, "IOReadBandwidthMax"))
- v = l->rbps_max;
- else
- v = l->wbps_max;
-
- if (v == CGROUP_LIMIT_MAX)
+ type = cgroup_io_limit_type_from_string(property);
+ if (type < 0 || l->limits[type] == cgroup_io_limit_defaults[type])
continue;
- r = sd_bus_message_append(reply, "(st)", l->path, v);
+ r = sd_bus_message_append(reply, "(st)", l->path, l->limits[type]);
if (r < 0)
return r;
}
UnitSetPropertiesMode mode,
sd_bus_error *error) {
+ CGroupIOLimitType iol_type;
int r;
assert(u);
return 1;
- } else if (streq(name, "IOReadBandwidthMax") || streq(name, "IOWriteBandwidthMax")) {
+ } else if ((iol_type = cgroup_io_limit_type_from_string(name)) >= 0) {
const char *path;
- bool read = true;
unsigned n = 0;
uint64_t u64;
- if (streq(name, "IOWriteBandwidthMax"))
- read = false;
-
r = sd_bus_message_enter_container(message, 'a', "(st)");
if (r < 0)
return r;
}
if (!a) {
+ CGroupIOLimitType type;
+
a = new0(CGroupIODeviceLimit, 1);
if (!a)
return -ENOMEM;
return -ENOMEM;
}
- a->rbps_max = CGROUP_LIMIT_MAX;
- a->wbps_max = CGROUP_LIMIT_MAX;
+ for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
+ a->limits[type] = cgroup_io_limit_defaults[type];
LIST_PREPEND(device_limits, c->io_device_limits, a);
}
- if (read)
- a->rbps_max = u64;
- else
- a->wbps_max = u64;
+ a->limits[iol_type] = u64;
}
n++;
if (n == 0) {
LIST_FOREACH(device_limits, a, c->io_device_limits)
- if (read)
- a->rbps_max = CGROUP_LIMIT_MAX;
- else
- a->wbps_max = CGROUP_LIMIT_MAX;
+ a->limits[iol_type] = cgroup_io_limit_defaults[iol_type];
}
unit_invalidate_cgroup(u, CGROUP_MASK_IO);
if (!f)
return -ENOMEM;
- if (read) {
- fputs("IOReadBandwidthMax=\n", f);
- LIST_FOREACH(device_limits, a, c->io_device_limits)
- if (a->rbps_max != CGROUP_LIMIT_MAX)
- fprintf(f, "IOReadBandwidthMax=%s %" PRIu64 "\n", a->path, a->rbps_max);
- } else {
- fputs("IOWriteBandwidthMax=\n", f);
- LIST_FOREACH(device_limits, a, c->io_device_limits)
- if (a->wbps_max != CGROUP_LIMIT_MAX)
- fprintf(f, "IOWriteBandwidthMax=%s %" PRIu64 "\n", a->path, a->wbps_max);
- }
+ fprintf(f, "%s=\n", name);
+ LIST_FOREACH(device_limits, a, c->io_device_limits)
+ if (a->limits[iol_type] != cgroup_io_limit_defaults[iol_type])
+ fprintf(f, "%s=%s %" PRIu64 "\n", name, a->path, a->limits[iol_type]);
r = fflush_and_check(f);
if (r < 0)
_cleanup_free_ char *path = NULL;
CGroupIODeviceLimit *l = NULL, *t;
CGroupContext *c = data;
+ CGroupIOLimitType type;
const char *limit;
uint64_t num;
- bool read;
size_t n;
int r;
assert(lvalue);
assert(rvalue);
- read = streq("IOReadBandwidthMax", lvalue);
+ type = cgroup_io_limit_type_from_string(lvalue);
+ assert(type >= 0);
if (isempty(rvalue)) {
LIST_FOREACH(device_limits, l, c->io_device_limits)
- if (read)
- l->rbps_max = CGROUP_LIMIT_MAX;
- else
- l->wbps_max = CGROUP_LIMIT_MAX;
+ l->limits[type] = cgroup_io_limit_defaults[type];
return 0;
}
}
if (!l) {
+ CGroupIOLimitType ttype;
+
l = new0(CGroupIODeviceLimit, 1);
if (!l)
return log_oom();
l->path = path;
path = NULL;
- l->rbps_max = CGROUP_LIMIT_MAX;
- l->wbps_max = CGROUP_LIMIT_MAX;
+ for (ttype = 0; ttype < _CGROUP_IO_LIMIT_TYPE_MAX; ttype++)
+ l->limits[ttype] = cgroup_io_limit_defaults[ttype];
LIST_PREPEND(device_limits, c->io_device_limits, l);
}
- if (read)
- l->rbps_max = num;
- else
- l->wbps_max = num;
+ l->limits[type] = num;
return 0;
}
r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
}
- } else if (STR_IN_SET(field, "IOReadBandwidthMax", "IOWriteBandwidthMax",
- "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
+ } else if (cgroup_io_limit_type_from_string(field) >= 0 || STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
if (isempty(eq))
r = sd_bus_message_append(m, "v", "a(st)", 0);
return 0;
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "IOReadBandwidthMax") || streq(name, "IOWriteBandwidthMax") ||
+ } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (cgroup_io_limit_type_from_string(name) >= 0 ||
streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
const char *path;
uint64_t bandwidth;