mirror of
https://github.com/systemd/systemd.git
synced 2025-03-31 14:50:15 +03:00
core: introduce CGroupIOLimitType enums
Currently, there are two cgroup IO limits, bandwidth max for read and write, and they are hard-coded in various places. This is fine for two limits but IO is expected to grow more limits - low, high and max limits for bandwidth and IOPS - and hard-coding each limit won't make sense. This patch replaces hard-coded limits with an array indexed by CGroupIOLimitType and accompanying string and default value tables so that new limits can be added trivially.
This commit is contained in:
parent
4e080f502a
commit
9be572497d
@ -2269,6 +2269,18 @@ int cg_weight_parse(const char *s, uint64_t *ret) {
|
||||
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;
|
||||
|
@ -72,6 +72,20 @@ static inline bool CGROUP_WEIGHT_IS_OK(uint64_t x) {
|
||||
(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)
|
||||
|
@ -184,20 +184,16 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
|
||||
|
||||
LIST_FOREACH(device_limits, il, c->io_device_limits) {
|
||||
char buf[FORMAT_BYTES_MAX];
|
||||
CGroupIOLimitType type;
|
||||
|
||||
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));
|
||||
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)
|
||||
@ -442,9 +438,9 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@ -452,17 +448,18 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M
|
||||
if (r < 0)
|
||||
continue;
|
||||
|
||||
if (l->rbps_max != CGROUP_LIMIT_MAX) {
|
||||
xsprintf(rbps_buf, "%" PRIu64, l->rbps_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");
|
||||
}
|
||||
}
|
||||
|
||||
if (l->wbps_max != CGROUP_LIMIT_MAX) {
|
||||
xsprintf(wbps_buf, "%" PRIu64, l->wbps_max);
|
||||
n++;
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include "list.h"
|
||||
#include "time-util.h"
|
||||
#include "cgroup-util.h"
|
||||
|
||||
typedef struct CGroupContext CGroupContext;
|
||||
typedef struct CGroupDeviceAllow CGroupDeviceAllow;
|
||||
@ -64,8 +65,7 @@ struct CGroupIODeviceWeight {
|
||||
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 {
|
||||
|
@ -80,17 +80,13 @@ static int property_get_io_device_limits(
|
||||
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;
|
||||
}
|
||||
@ -273,6 +269,7 @@ int bus_cgroup_set_property(
|
||||
UnitSetPropertiesMode mode,
|
||||
sd_bus_error *error) {
|
||||
|
||||
CGroupIOLimitType iol_type;
|
||||
int r;
|
||||
|
||||
assert(u);
|
||||
@ -416,15 +413,11 @@ int bus_cgroup_set_property(
|
||||
|
||||
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;
|
||||
@ -442,6 +435,8 @@ int bus_cgroup_set_property(
|
||||
}
|
||||
|
||||
if (!a) {
|
||||
CGroupIOLimitType type;
|
||||
|
||||
a = new0(CGroupIODeviceLimit, 1);
|
||||
if (!a)
|
||||
return -ENOMEM;
|
||||
@ -452,16 +447,13 @@ int bus_cgroup_set_property(
|
||||
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++;
|
||||
@ -481,10 +473,7 @@ int bus_cgroup_set_property(
|
||||
|
||||
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);
|
||||
@ -493,17 +482,10 @@ int bus_cgroup_set_property(
|
||||
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)
|
||||
|
@ -3023,9 +3023,9 @@ int config_parse_io_limit(
|
||||
_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;
|
||||
|
||||
@ -3033,14 +3033,12 @@ int config_parse_io_limit(
|
||||
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;
|
||||
}
|
||||
|
||||
@ -3080,22 +3078,21 @@ int config_parse_io_limit(
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -284,8 +284,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
|
||||
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);
|
||||
|
@ -4447,7 +4447,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
|
||||
|
||||
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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user