summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Down <chris@chrisdown.name>2019-03-28 12:50:50 +0000
committerChris Down <chris@chrisdown.name>2019-04-03 14:28:32 +0100
commit03d980dbd0b46d6b3f7010eed8b7fc2519e7a1e5 (patch)
tree69840c591266642902ab78692cf645860f614d4b
parent51be9a8c41e1d6e6a15bf90c60318611edbaab14 (diff)
downloadsystemd-03d980dbd0b46d6b3f7010eed8b7fc2519e7a1e5.tar.gz
temp
-rw-r--r--src/basic/cgroup-util.h1
-rw-r--r--src/core/cgroup.c63
-rw-r--r--src/core/cgroup.h2
-rw-r--r--src/core/dbus-cgroup.c1
-rw-r--r--src/core/load-fragment-gperf.gperf.m41
-rw-r--r--src/core/load-fragment.c11
-rw-r--r--src/systemctl/systemctl.c3
7 files changed, 74 insertions, 8 deletions
diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h
index a39ab451b9..73b4611536 100644
--- a/src/basic/cgroup-util.h
+++ b/src/basic/cgroup-util.h
@@ -78,6 +78,7 @@ bool cpu_accounting_is_cheap(void);
#define CGROUP_WEIGHT_MAX UINT64_C(10000)
#define CGROUP_WEIGHT_DEFAULT UINT64_C(100)
+#define CGROUP_LIMIT_INVALID ((uint64_t) -2)
#define CGROUP_LIMIT_MIN UINT64_C(0)
#define CGROUP_LIMIT_MAX ((uint64_t) -1)
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index ad67ba0438..4524edc140 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -104,6 +104,10 @@ void cgroup_context_init(CGroupContext *c) {
.cpu_shares = CGROUP_CPU_SHARES_INVALID,
.startup_cpu_shares = CGROUP_CPU_SHARES_INVALID,
+ .default_memory_low = CGROUP_LIMIT_INVALID,
+
+ .memory_low = CGROUP_LIMIT_INVALID,
+
.memory_high = CGROUP_LIMIT_MAX,
.memory_max = CGROUP_LIMIT_MAX,
.memory_swap_max = CGROUP_LIMIT_MAX,
@@ -232,6 +236,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
"%sStartupIOWeight=%" PRIu64 "\n"
"%sBlockIOWeight=%" PRIu64 "\n"
"%sStartupBlockIOWeight=%" PRIu64 "\n"
+ "%sDefaultMemoryLow=%" PRIu64 "\n"
"%sMemoryMin=%" PRIu64 "\n"
"%sMemoryLow=%" PRIu64 "\n"
"%sMemoryHigh=%" PRIu64 "\n"
@@ -257,6 +262,7 @@ 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->default_memory_low,
prefix, c->memory_min,
prefix, c->memory_low,
prefix, c->memory_high,
@@ -380,6 +386,36 @@ int cgroup_add_device_allow(CGroupContext *c, const char *dev, const char *mode)
return 0;
}
+static uint64_t unit_get_ancestor_memory_low(Unit *u) {
+ CGroupContext *c;
+
+ /* 1. Is MemoryLow set in this unit? If so, use that.
+ * 2. Is DefaultMemoryLow set in this unit? If so, use that.
+ * 3. Is DefaultMemoryLow set in any ancestor? If so, use that.
+ * 4. Otherwise, return CGROUP_LIMIT_MIN. */
+
+ assert(u);
+
+ c = unit_get_cgroup_context(u);
+
+ if (c->memory_low != CGROUP_LIMIT_INVALID)
+ return c->memory_low;
+
+ if (c->default_memory_low != CGROUP_LIMIT_INVALID)
+ return c->default_memory_low;
+
+ while (UNIT_ISSET(u->slice)) {
+ u = UNIT_DEREF(u->slice);
+ c = unit_get_cgroup_context(u);
+
+ if (c->default_memory_low != CGROUP_LIMIT_INVALID)
+ return c->default_memory_low;
+ }
+
+ /* We've reached the root, but nobody had DefaultMemoryLow set, so set it to the kernel default. */
+ return CGROUP_LIMIT_MIN;
+}
+
static void cgroup_xattr_apply(Unit *u) {
char ids[SD_ID128_STRING_MAX];
int r;
@@ -875,8 +911,14 @@ static void cgroup_apply_blkio_device_limit(Unit *u, const char *dev_path, uint6
(void) set_attribute_and_warn(u, "blkio", "blkio.throttle.write_bps_device", buf);
}
-static bool cgroup_context_has_unified_memory_config(CGroupContext *c) {
- return c->memory_min > 0 || c->memory_low > 0 || c->memory_high != CGROUP_LIMIT_MAX || c->memory_max != CGROUP_LIMIT_MAX || c->memory_swap_max != CGROUP_LIMIT_MAX;
+static bool unit_has_unified_memory_config(Unit *u) {
+ CGroupContext *c;
+
+ assert(u);
+
+ c = unit_get_cgroup_context(u);
+
+ return c->memory_min > 0 || unit_get_ancestor_memory_low(u) > 0 || c->memory_high != CGROUP_LIMIT_MAX || c->memory_max != CGROUP_LIMIT_MAX || c->memory_swap_max != CGROUP_LIMIT_MAX;
}
static void cgroup_apply_unified_memory_limit(Unit *u, const char *file, uint64_t v) {
@@ -1125,7 +1167,7 @@ static void cgroup_context_apply(
if (cg_all_unified() > 0) {
uint64_t max, swap_max = CGROUP_LIMIT_MAX;
- if (cgroup_context_has_unified_memory_config(c)) {
+ if (unit_has_unified_memory_config(u)) {
max = c->memory_max;
swap_max = c->memory_swap_max;
} else {
@@ -1136,7 +1178,7 @@ static void cgroup_context_apply(
}
cgroup_apply_unified_memory_limit(u, "memory.min", c->memory_min);
- cgroup_apply_unified_memory_limit(u, "memory.low", c->memory_low);
+ cgroup_apply_unified_memory_limit(u, "memory.low", unit_get_ancestor_memory_low(u));
cgroup_apply_unified_memory_limit(u, "memory.high", c->memory_high);
cgroup_apply_unified_memory_limit(u, "memory.max", max);
cgroup_apply_unified_memory_limit(u, "memory.swap.max", swap_max);
@@ -1145,7 +1187,7 @@ static void cgroup_context_apply(
char buf[DECIMAL_STR_MAX(uint64_t) + 1];
uint64_t val;
- if (cgroup_context_has_unified_memory_config(c)) {
+ if (unit_has_unified_memory_config(u)) {
val = c->memory_max;
log_cgroup_compat(u, "Applying MemoryMax=%" PRIi64 " as MemoryLimit=", val);
} else
@@ -1319,8 +1361,13 @@ static bool unit_get_needs_bpf_firewall(Unit *u) {
return false;
}
-static CGroupMask cgroup_context_get_mask(CGroupContext *c) {
+static CGroupMask unit_get_cgroup_mask(Unit *u) {
CGroupMask mask = 0;
+ CGroupContext *c;
+
+ assert(u);
+
+ c = unit_get_cgroup_context(u);
/* Figure out which controllers we need, based on the cgroup context object */
@@ -1337,7 +1384,7 @@ static CGroupMask cgroup_context_get_mask(CGroupContext *c) {
if (c->memory_accounting ||
c->memory_limit != CGROUP_LIMIT_MAX ||
- cgroup_context_has_unified_memory_config(c))
+ unit_has_unified_memory_config(u))
mask |= CGROUP_MASK_MEMORY;
if (c->device_allow ||
@@ -1376,7 +1423,7 @@ CGroupMask unit_get_own_mask(Unit *u) {
if (!c)
return 0;
- return (cgroup_context_get_mask(c) | unit_get_bpf_mask(u) | unit_get_delegate_mask(u)) & ~unit_get_ancestor_disable_mask(u);
+ return (unit_get_cgroup_mask(u) | unit_get_bpf_mask(u) | unit_get_delegate_mask(u)) & ~unit_get_ancestor_disable_mask(u);
}
CGroupMask unit_get_delegate_mask(Unit *u) {
diff --git a/src/core/cgroup.h b/src/core/cgroup.h
index 51e7c96d60..eadb003cab 100644
--- a/src/core/cgroup.h
+++ b/src/core/cgroup.h
@@ -95,6 +95,8 @@ struct CGroupContext {
LIST_HEAD(CGroupIODeviceLimit, io_device_limits);
LIST_HEAD(CGroupIODeviceLatency, io_device_latencies);
+ uint64_t default_memory_low;
+
uint64_t memory_min;
uint64_t memory_low;
uint64_t memory_high;
diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c
index 4615aeaf66..38cfcaee28 100644
--- a/src/core/dbus-cgroup.c
+++ b/src/core/dbus-cgroup.c
@@ -348,6 +348,7 @@ 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("DefaultMemoryLow", "t", NULL, offsetof(CGroupContext, default_memory_low), 0),
SD_BUS_PROPERTY("MemoryMin", "t", NULL, offsetof(CGroupContext, memory_min), 0),
SD_BUS_PROPERTY("MemoryLow", "t", NULL, offsetof(CGroupContext, memory_low), 0),
SD_BUS_PROPERTY("MemoryHigh", "t", NULL, offsetof(CGroupContext, memory_high), 0),
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 7fb1e6cc8b..facba03452 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -172,6 +172,7 @@ $1.CPUQuota, config_parse_cpu_quota, 0,
$1.CPUQuotaPeriodSec, config_parse_sec_def_infinity, 0, offsetof($1, cgroup_context.cpu_quota_period_usec)
$1.MemoryAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.memory_accounting)
$1.MemoryMin, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
+$1.DefaultMemoryLow, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
$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)
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 6acfd9b8ea..d25246d9dc 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -3104,6 +3104,17 @@ int config_parse_memory_limit(
}
}
+ /* Defaults come first, so that they can be overridden later. DefaultMemoryXXX= with no rvalue
+ * resets. */
+ if (streq(lvalue, "DefaultMemoryLow")) {
+ if (isempty(rvalue)) {
+ c->default_memory_low = CGROUP_LIMIT_MIN;
+ } else {
+ c->default_memory_low = bytes;
+ c->memory_low = bytes;
+ }
+ }
+
if (streq(lvalue, "MemoryMin"))
c->memory_min = bytes;
else if (streq(lvalue, "MemoryLow"))
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 92bbcfd276..c9edefdd82 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -4129,6 +4129,8 @@ typedef struct UnitStatusInfo {
uint64_t ip_ingress_bytes;
uint64_t ip_egress_bytes;
+ uint64_t default_memory_low;
+
LIST_HEAD(ExecStatusInfo, exec);
} UnitStatusInfo;
@@ -5479,6 +5481,7 @@ static int show_one(
{ "Where", "s", NULL, offsetof(UnitStatusInfo, where) },
{ "What", "s", NULL, offsetof(UnitStatusInfo, what) },
{ "MemoryCurrent", "t", NULL, offsetof(UnitStatusInfo, memory_current) },
+ { "DefaultMemoryLow", "t", NULL, offsetof(UnitStatusInfo, default_memory_low) },
{ "MemoryMin", "t", NULL, offsetof(UnitStatusInfo, memory_min) },
{ "MemoryLow", "t", NULL, offsetof(UnitStatusInfo, memory_low) },
{ "MemoryHigh", "t", NULL, offsetof(UnitStatusInfo, memory_high) },