summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/cgroup.c63
-rw-r--r--src/core/cgroup.h4
-rw-r--r--src/core/dbus-cgroup.c82
-rw-r--r--src/core/dbus-execute.c2
-rw-r--r--src/core/load-fragment-gperf.gperf.m43
-rw-r--r--src/core/load-fragment.c25
6 files changed, 123 insertions, 56 deletions
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 0fb63b1bd1..fbe69df4e9 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -46,7 +46,10 @@ void cgroup_context_init(CGroupContext *c) {
c->startup_cpu_shares = CGROUP_CPU_SHARES_INVALID;
c->cpu_quota_per_sec_usec = USEC_INFINITY;
- c->memory_limit = (uint64_t) -1;
+ c->memory_high = CGROUP_LIMIT_MAX;
+ c->memory_max = CGROUP_LIMIT_MAX;
+
+ c->memory_limit = CGROUP_LIMIT_MAX;
c->io_weight = CGROUP_WEIGHT_INVALID;
c->startup_io_weight = CGROUP_WEIGHT_INVALID;
@@ -147,6 +150,9 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
"%sStartupIOWeight=%" PRIu64 "\n"
"%sBlockIOWeight=%" PRIu64 "\n"
"%sStartupBlockIOWeight=%" PRIu64 "\n"
+ "%sMemoryLow=%" PRIu64 "\n"
+ "%sMemoryHigh=%" PRIu64 "\n"
+ "%sMemoryMax=%" PRIu64 "\n"
"%sMemoryLimit=%" PRIu64 "\n"
"%sTasksMax=%" PRIu64 "\n"
"%sDevicePolicy=%s\n"
@@ -163,6 +169,9 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
prefix, c->startup_io_weight,
prefix, c->blockio_weight,
prefix, c->startup_blockio_weight,
+ prefix, c->memory_low,
+ prefix, c->memory_high,
+ prefix, c->memory_max,
prefix, c->memory_limit,
prefix, c->tasks_max,
prefix, cgroup_device_policy_to_string(c->device_policy),
@@ -496,6 +505,23 @@ static unsigned cgroup_apply_blkio_device_limit(const char *path, const char *de
return n;
}
+static bool cgroup_context_has_unified_memory_config(CGroupContext *c) {
+ return c->memory_low > 0 || c->memory_high != CGROUP_LIMIT_MAX || c->memory_max != CGROUP_LIMIT_MAX;
+}
+
+static void cgroup_apply_unified_memory_limit(const char *path, const char *file, uint64_t v) {
+ char buf[DECIMAL_STR_MAX(uint64_t) + 1] = "max";
+ int r;
+
+ if (v != CGROUP_LIMIT_MAX)
+ xsprintf(buf, "%" PRIu64 "\n", v);
+
+ r = cg_set_attribute("memory", path, file, buf);
+ if (r < 0)
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
+ "Failed to set %s on %s: %m", file, path);
+}
+
void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, ManagerState state) {
bool is_root;
int r;
@@ -662,26 +688,30 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M
}
if ((mask & CGROUP_MASK_MEMORY) && !is_root) {
- if (c->memory_limit != (uint64_t) -1) {
- char buf[DECIMAL_STR_MAX(uint64_t) + 1];
-
- sprintf(buf, "%" PRIu64 "\n", c->memory_limit);
+ if (cg_unified() > 0) {
+ uint64_t max = c->memory_max;
- if (cg_unified() <= 0)
- r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf);
+ if (cgroup_context_has_unified_memory_config(c))
+ max = c->memory_max;
else
- r = cg_set_attribute("memory", path, "memory.max", buf);
+ max = c->memory_limit;
+ cgroup_apply_unified_memory_limit(path, "memory.low", c->memory_low);
+ cgroup_apply_unified_memory_limit(path, "memory.high", c->memory_high);
+ cgroup_apply_unified_memory_limit(path, "memory.max", max);
} else {
- if (cg_unified() <= 0)
- r = cg_set_attribute("memory", path, "memory.limit_in_bytes", "-1");
+ char buf[DECIMAL_STR_MAX(uint64_t) + 1];
+
+ if (c->memory_limit != CGROUP_LIMIT_MAX)
+ xsprintf(buf, "%" PRIu64 "\n", c->memory_limit);
else
- r = cg_set_attribute("memory", path, "memory.max", "max");
- }
+ xsprintf(buf, "%" PRIu64 "\n", c->memory_max);
- if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
- "Failed to set memory.limit_in_bytes/memory.max on %s: %m", path);
+ r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf);
+ if (r < 0)
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
+ "Failed to set memory.limit_in_bytes on %s: %m", path);
+ }
}
if ((mask & CGROUP_MASK_DEVICES) && !is_root) {
@@ -778,7 +808,8 @@ CGroupMask cgroup_context_get_mask(CGroupContext *c) {
mask |= CGROUP_MASK_IO | CGROUP_MASK_BLKIO;
if (c->memory_accounting ||
- c->memory_limit != (uint64_t) -1)
+ c->memory_limit != CGROUP_LIMIT_MAX ||
+ cgroup_context_has_unified_memory_config(c))
mask |= CGROUP_MASK_MEMORY;
if (c->device_allow ||
diff --git a/src/core/cgroup.h b/src/core/cgroup.h
index 2b1edbafc4..ff87adfba1 100644
--- a/src/core/cgroup.h
+++ b/src/core/cgroup.h
@@ -94,6 +94,10 @@ struct CGroupContext {
LIST_HEAD(CGroupIODeviceWeight, io_device_weights);
LIST_HEAD(CGroupIODeviceLimit, io_device_limits);
+ uint64_t memory_low;
+ uint64_t memory_high;
+ uint64_t memory_max;
+
/* For legacy hierarchies */
uint64_t cpu_shares;
uint64_t startup_cpu_shares;
diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c
index eef1c47c14..27050b4507 100644
--- a/src/core/dbus-cgroup.c
+++ b/src/core/dbus-cgroup.c
@@ -228,6 +228,9 @@ const sd_bus_vtable bus_cgroup_vtable[] = {
SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, memory_accounting), 0),
+ SD_BUS_PROPERTY("MemoryLow", "t", NULL, offsetof(CGroupContext, memory_low), 0),
+ SD_BUS_PROPERTY("MemoryHigh", "t", NULL, offsetof(CGroupContext, memory_high), 0),
+ SD_BUS_PROPERTY("MemoryMax", "t", NULL, offsetof(CGroupContext, memory_max), 0),
SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0),
SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0),
SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0),
@@ -260,7 +263,7 @@ static int bus_cgroup_set_transient_property(
if (mode != UNIT_CHECK) {
c->delegate = b;
- unit_write_drop_in_private(u, mode, name, b ? "Delegate=yes" : "Delegate=no");
+ unit_write_drop_in_private(u, mode, name, b ? "Delegate=yes\n" : "Delegate=no\n");
}
return 1;
@@ -295,7 +298,7 @@ int bus_cgroup_set_property(
if (mode != UNIT_CHECK) {
c->cpu_accounting = b;
unit_invalidate_cgroup(u, CGROUP_MASK_CPUACCT|CGROUP_MASK_CPU);
- unit_write_drop_in_private(u, mode, name, b ? "CPUAccounting=yes" : "CPUAccounting=no");
+ unit_write_drop_in_private(u, mode, name, b ? "CPUAccounting=yes\n" : "CPUAccounting=no\n");
}
return 1;
@@ -315,9 +318,9 @@ int bus_cgroup_set_property(
unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
if (shares == CGROUP_CPU_SHARES_INVALID)
- unit_write_drop_in_private(u, mode, name, "CPUShares=");
+ unit_write_drop_in_private(u, mode, name, "CPUShares=\n");
else
- unit_write_drop_in_private_format(u, mode, name, "CPUShares=%" PRIu64, shares);
+ unit_write_drop_in_private_format(u, mode, name, "CPUShares=%" PRIu64 "\n", shares);
}
return 1;
@@ -337,9 +340,9 @@ int bus_cgroup_set_property(
unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
if (shares == CGROUP_CPU_SHARES_INVALID)
- unit_write_drop_in_private(u, mode, name, "StartupCPUShares=");
+ unit_write_drop_in_private(u, mode, name, "StartupCPUShares=\n");
else
- unit_write_drop_in_private_format(u, mode, name, "StartupCPUShares=%" PRIu64, shares);
+ unit_write_drop_in_private_format(u, mode, name, "StartupCPUShares=%" PRIu64 "\n", shares);
}
return 1;
@@ -357,7 +360,7 @@ int bus_cgroup_set_property(
if (mode != UNIT_CHECK) {
c->cpu_quota_per_sec_usec = u64;
unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
- unit_write_drop_in_private_format(u, mode, "CPUQuota", "CPUQuota=%0.f%%", (double) (c->cpu_quota_per_sec_usec / 10000));
+ unit_write_drop_in_private_format(u, mode, "CPUQuota", "CPUQuota=%0.f%%\n", (double) (c->cpu_quota_per_sec_usec / 10000));
}
return 1;
@@ -372,7 +375,7 @@ int bus_cgroup_set_property(
if (mode != UNIT_CHECK) {
c->io_accounting = b;
unit_invalidate_cgroup(u, CGROUP_MASK_IO);
- unit_write_drop_in_private(u, mode, name, b ? "IOAccounting=yes" : "IOAccounting=no");
+ unit_write_drop_in_private(u, mode, name, b ? "IOAccounting=yes\n" : "IOAccounting=no\n");
}
return 1;
@@ -392,9 +395,9 @@ int bus_cgroup_set_property(
unit_invalidate_cgroup(u, CGROUP_MASK_IO);
if (weight == CGROUP_WEIGHT_INVALID)
- unit_write_drop_in_private(u, mode, name, "IOWeight=");
+ unit_write_drop_in_private(u, mode, name, "IOWeight=\n");
else
- unit_write_drop_in_private_format(u, mode, name, "IOWeight=%" PRIu64, weight);
+ unit_write_drop_in_private_format(u, mode, name, "IOWeight=%" PRIu64 "\n", weight);
}
return 1;
@@ -414,9 +417,9 @@ int bus_cgroup_set_property(
unit_invalidate_cgroup(u, CGROUP_MASK_IO);
if (weight == CGROUP_WEIGHT_INVALID)
- unit_write_drop_in_private(u, mode, name, "StartupIOWeight=");
+ unit_write_drop_in_private(u, mode, name, "StartupIOWeight=\n");
else
- unit_write_drop_in_private_format(u, mode, name, "StartupIOWeight=%" PRIu64, weight);
+ unit_write_drop_in_private_format(u, mode, name, "StartupIOWeight=%" PRIu64 "\n", weight);
}
return 1;
@@ -589,7 +592,7 @@ int bus_cgroup_set_property(
if (mode != UNIT_CHECK) {
c->blockio_accounting = b;
unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
- unit_write_drop_in_private(u, mode, name, b ? "BlockIOAccounting=yes" : "BlockIOAccounting=no");
+ unit_write_drop_in_private(u, mode, name, b ? "BlockIOAccounting=yes\n" : "BlockIOAccounting=no\n");
}
return 1;
@@ -609,9 +612,9 @@ int bus_cgroup_set_property(
unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
if (weight == CGROUP_BLKIO_WEIGHT_INVALID)
- unit_write_drop_in_private(u, mode, name, "BlockIOWeight=");
+ unit_write_drop_in_private(u, mode, name, "BlockIOWeight=\n");
else
- unit_write_drop_in_private_format(u, mode, name, "BlockIOWeight=%" PRIu64, weight);
+ unit_write_drop_in_private_format(u, mode, name, "BlockIOWeight=%" PRIu64 "\n", weight);
}
return 1;
@@ -623,7 +626,7 @@ int bus_cgroup_set_property(
if (r < 0)
return r;
- if (CGROUP_BLKIO_WEIGHT_IS_OK(weight))
+ if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight))
return sd_bus_error_set_errnof(error, EINVAL, "StartupBlockIOWeight value out of range");
if (mode != UNIT_CHECK) {
@@ -631,9 +634,9 @@ int bus_cgroup_set_property(
unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
if (weight == CGROUP_BLKIO_WEIGHT_INVALID)
- unit_write_drop_in_private(u, mode, name, "StartupBlockIOWeight=");
+ unit_write_drop_in_private(u, mode, name, "StartupBlockIOWeight=\n");
else
- unit_write_drop_in_private_format(u, mode, name, "StartupBlockIOWeight=%" PRIu64, weight);
+ unit_write_drop_in_private_format(u, mode, name, "StartupBlockIOWeight=%" PRIu64 "\n", weight);
}
return 1;
@@ -821,7 +824,32 @@ int bus_cgroup_set_property(
if (mode != UNIT_CHECK) {
c->memory_accounting = b;
unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
- unit_write_drop_in_private(u, mode, name, b ? "MemoryAccounting=yes" : "MemoryAccounting=no");
+ unit_write_drop_in_private(u, mode, name, b ? "MemoryAccounting=yes\n" : "MemoryAccounting=no\n");
+ }
+
+ return 1;
+
+ } else if (STR_IN_SET(name, "MemoryLow", "MemoryHigh", "MemoryMax")) {
+ uint64_t v;
+
+ r = sd_bus_message_read(message, "t", &v);
+ if (r < 0)
+ return r;
+
+ if (mode != UNIT_CHECK) {
+ if (streq(name, "MemoryLow"))
+ c->memory_low = v;
+ else if (streq(name, "MemoryHigh"))
+ c->memory_high = v;
+ else
+ c->memory_max = v;
+
+ unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
+
+ if (v == CGROUP_LIMIT_MAX)
+ unit_write_drop_in_private_format(u, mode, name, "%s=max\n", name);
+ else
+ unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64 "\n", name, v);
}
return 1;
@@ -838,9 +866,9 @@ int bus_cgroup_set_property(
unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
if (limit == (uint64_t) -1)
- unit_write_drop_in_private(u, mode, name, "MemoryLimit=infinity");
+ unit_write_drop_in_private(u, mode, name, "MemoryLimit=infinity\n");
else
- unit_write_drop_in_private_format(u, mode, name, "MemoryLimit=%" PRIu64, limit);
+ unit_write_drop_in_private_format(u, mode, name, "MemoryLimit=%" PRIu64 "\n", limit);
}
return 1;
@@ -858,13 +886,9 @@ int bus_cgroup_set_property(
return -EINVAL;
if (mode != UNIT_CHECK) {
- char *buf;
-
c->device_policy = p;
unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES);
-
- buf = strjoina("DevicePolicy=", policy);
- unit_write_drop_in_private(u, mode, name, buf);
+ unit_write_drop_in_private_format(u, mode, name, "DevicePolicy=%s\n", policy);
}
return 1;
@@ -968,7 +992,7 @@ int bus_cgroup_set_property(
if (mode != UNIT_CHECK) {
c->tasks_accounting = b;
unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
- unit_write_drop_in_private(u, mode, name, b ? "TasksAccounting=yes" : "TasksAccounting=no");
+ unit_write_drop_in_private(u, mode, name, b ? "TasksAccounting=yes\n" : "TasksAccounting=no\n");
}
return 1;
@@ -985,9 +1009,9 @@ int bus_cgroup_set_property(
unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
if (limit == (uint64_t) -1)
- unit_write_drop_in_private(u, mode, name, "TasksMax=infinity");
+ unit_write_drop_in_private(u, mode, name, "TasksMax=infinity\n");
else
- unit_write_drop_in_private_format(u, mode, name, "TasksMax=%" PRIu64, limit);
+ unit_write_drop_in_private_format(u, mode, name, "TasksMax=%" PRIu64 "\n", limit);
}
return 1;
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index 06943c6365..e21956def1 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -987,7 +987,7 @@ int bus_exec_context_set_transient_property(
}
c->working_directory_missing_ok = missing_ok;
- unit_write_drop_in_private_format(u, mode, name, "WorkingDirectory=%s%s", missing_ok ? "-" : "", s);
+ unit_write_drop_in_private_format(u, mode, name, "WorkingDirectory=%s%s\n", missing_ok ? "-" : "", s);
}
return 1;
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 8193418980..00bdc238ce 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -117,6 +117,9 @@ $1.CPUShares, config_parse_cpu_shares, 0,
$1.StartupCPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.startup_cpu_shares)
$1.CPUQuota, config_parse_cpu_quota, 0, offsetof($1, cgroup_context)
$1.MemoryAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.memory_accounting)
+$1.MemoryLow, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
+$1.MemoryHigh, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
+$1.MemoryMax, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
$1.MemoryLimit, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
$1.DeviceAllow, config_parse_device_allow, 0, offsetof($1, cgroup_context)
$1.DevicePolicy, config_parse_device_policy, 0, offsetof($1, cgroup_context.device_policy)
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 86b4fb071b..09d3f65c77 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -2793,21 +2793,26 @@ int config_parse_memory_limit(
void *userdata) {
CGroupContext *c = data;
- uint64_t bytes;
+ uint64_t bytes = CGROUP_LIMIT_MAX;
int r;
- if (isempty(rvalue) || streq(rvalue, "infinity")) {
- c->memory_limit = (uint64_t) -1;
- return 0;
+ if (!isempty(rvalue) && !streq(rvalue, "infinity") && !streq(rvalue, "max")) {
+ r = parse_size(rvalue, 1024, &bytes);
+ if (r < 0 || bytes < 1) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Memory limit '%s' invalid. Ignoring.", rvalue);
+ return 0;
+ }
}
- r = parse_size(rvalue, 1024, &bytes);
- if (r < 0 || bytes < 1) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Memory limit '%s' invalid. Ignoring.", rvalue);
- return 0;
- }
+ if (streq(lvalue, "MemoryLow"))
+ c->memory_low = bytes;
+ else if (streq(lvalue, "MemoryHigh"))
+ c->memory_high = bytes;
+ else if (streq(lvalue, "MemoryMax"))
+ c->memory_max = bytes;
+ else
+ c->memory_limit = bytes;
- c->memory_limit = bytes;
return 0;
}