diff options
-rw-r--r-- | man/systemd.resource-control.xml | 18 | ||||
-rw-r--r-- | src/core/cgroup.c | 12 | ||||
-rw-r--r-- | src/core/cgroup.h | 1 | ||||
-rw-r--r-- | src/core/dbus-cgroup.c | 5 | ||||
-rw-r--r-- | src/core/load-fragment-gperf.gperf.m4 | 1 | ||||
-rw-r--r-- | src/core/load-fragment.c | 6 | ||||
-rw-r--r-- | src/systemctl/systemctl.c | 11 |
7 files changed, 48 insertions, 6 deletions
diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml index 84dbfa2ff3..c11f420fe5 100644 --- a/man/systemd.resource-control.xml +++ b/man/systemd.resource-control.xml @@ -326,6 +326,24 @@ </varlistentry> <varlistentry> + <term><varname>MemorySwapMax=<replaceable>bytes</replaceable></varname></term> + + <listitem> + <para>Specify the absolute limit on swap usage of the executed processes in this unit.</para> + + <para>Takes a swap size in bytes. If the value is suffixed with K, M, G or T, the specified swap size is + parsed as Kilobytes, Megabytes, Gigabytes, or Terabytes (with the base 1024), respectively. If assigned the + special value <literal>infinity</literal>, no swap limit is applied. This controls the + <literal>memory.swap.max</literal> control group attribute. For details about this control group attribute, + see <ulink url="https://www.kernel.org/doc/Documentation/cgroup-v2.txt">cgroup-v2.txt</ulink>.</para> + + <para>Implies <literal>MemoryAccounting=true</literal>.</para> + + <para>This setting is supported only if the unified control group hierarchy is used.</para> + </listitem> + </varlistentry> + + <varlistentry> <term><varname>MemoryLimit=<replaceable>bytes</replaceable></varname></term> <listitem> diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 20f9f9fc7e..7873f88785 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -66,6 +66,7 @@ void cgroup_context_init(CGroupContext *c) { c->memory_high = CGROUP_LIMIT_MAX; c->memory_max = CGROUP_LIMIT_MAX; + c->memory_swap_max = CGROUP_LIMIT_MAX; c->memory_limit = CGROUP_LIMIT_MAX; @@ -173,6 +174,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { "%sMemoryLow=%" PRIu64 "\n" "%sMemoryHigh=%" PRIu64 "\n" "%sMemoryMax=%" PRIu64 "\n" + "%sMemorySwapMax=%" PRIu64 "\n" "%sMemoryLimit=%" PRIu64 "\n" "%sTasksMax=%" PRIu64 "\n" "%sDevicePolicy=%s\n" @@ -194,6 +196,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { prefix, c->memory_low, prefix, c->memory_high, prefix, c->memory_max, + prefix, c->memory_swap_max, prefix, c->memory_limit, prefix, c->tasks_max, prefix, cgroup_device_policy_to_string(c->device_policy), @@ -617,7 +620,7 @@ static unsigned cgroup_apply_blkio_device_limit(Unit *u, const char *dev_path, u } 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; + return c->memory_low > 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) { @@ -848,10 +851,12 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) { if ((mask & CGROUP_MASK_MEMORY) && !is_root) { if (cg_all_unified() > 0) { uint64_t max = c->memory_max; + uint64_t swap_max = c->memory_swap_max; - if (cgroup_context_has_unified_memory_config(c)) + if (cgroup_context_has_unified_memory_config(c)) { max = c->memory_max; - else { + swap_max = c->memory_swap_max; + } else { max = c->memory_limit; if (max != CGROUP_LIMIT_MAX) @@ -861,6 +866,7 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) { cgroup_apply_unified_memory_limit(u, "memory.low", c->memory_low); 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); } else { char buf[DECIMAL_STR_MAX(uint64_t) + 1]; uint64_t val = c->memory_limit; diff --git a/src/core/cgroup.h b/src/core/cgroup.h index 2fe9cc4039..4cd168f63e 100644 --- a/src/core/cgroup.h +++ b/src/core/cgroup.h @@ -101,6 +101,7 @@ struct CGroupContext { uint64_t memory_low; uint64_t memory_high; uint64_t memory_max; + uint64_t memory_swap_max; /* For legacy hierarchies */ uint64_t cpu_shares; diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c index 2ca80d2996..c4067a95bf 100644 --- a/src/core/dbus-cgroup.c +++ b/src/core/dbus-cgroup.c @@ -233,6 +233,7 @@ const sd_bus_vtable bus_cgroup_vtable[] = { 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("MemorySwapMax", "t", NULL, offsetof(CGroupContext, memory_swap_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), @@ -875,7 +876,7 @@ int bus_cgroup_set_property( return 1; - } else if (STR_IN_SET(name, "MemoryLow", "MemoryHigh", "MemoryMax")) { + } else if (STR_IN_SET(name, "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax")) { uint64_t v; r = sd_bus_message_read(message, "t", &v); @@ -889,6 +890,8 @@ int bus_cgroup_set_property( c->memory_low = v; else if (streq(name, "MemoryHigh")) c->memory_high = v; + else if (streq(name, "MemorySwapMax")) + c->memory_swap_max = v; else c->memory_max = v; diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 420d32dbd7..0741aca616 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -131,6 +131,7 @@ $1.MemoryAccounting, config_parse_bool, 0, $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.MemorySwapMax, 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 d5185cf6a0..65ca9d8a33 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -2981,8 +2981,12 @@ int config_parse_memory_limit( c->memory_high = bytes; else if (streq(lvalue, "MemoryMax")) c->memory_max = bytes; - else + else if (streq(lvalue, "MemorySwapMax")) + c->memory_swap_max = bytes; + else if (streq(lvalue, "MemoryLimit")) c->memory_limit = bytes; + else + return -EINVAL; return 0; } diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 4b87bdceb2..682805045d 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3571,6 +3571,7 @@ typedef struct UnitStatusInfo { uint64_t memory_low; uint64_t memory_high; uint64_t memory_max; + uint64_t memory_swap_max; uint64_t memory_limit; uint64_t cpu_usage_nsec; uint64_t tasks_current; @@ -3883,7 +3884,8 @@ static void print_status_info( printf(" Memory: %s", format_bytes(buf, sizeof(buf), i->memory_current)); - if (i->memory_low > 0 || i->memory_high != CGROUP_LIMIT_MAX || i->memory_max != CGROUP_LIMIT_MAX || + if (i->memory_low > 0 || i->memory_high != CGROUP_LIMIT_MAX || + i->memory_max != CGROUP_LIMIT_MAX || i->memory_swap_max != CGROUP_LIMIT_MAX || i->memory_limit != CGROUP_LIMIT_MAX) { const char *prefix = ""; @@ -3900,6 +3902,10 @@ static void print_status_info( printf("%smax: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_max)); prefix = " "; } + if (i->memory_swap_max != CGROUP_LIMIT_MAX) { + printf("%sswap max: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_swap_max)); + prefix = " "; + } if (i->memory_limit != CGROUP_LIMIT_MAX) { printf("%slimit: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_limit)); prefix = " "; @@ -4140,6 +4146,8 @@ static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo * i->memory_high = u; else if (streq(name, "MemoryMax")) i->memory_max = u; + else if (streq(name, "MemorySwapMax")) + i->memory_swap_max = u; else if (streq(name, "MemoryLimit")) i->memory_limit = u; else if (streq(name, "TasksCurrent")) @@ -4655,6 +4663,7 @@ static int show_one( .memory_current = (uint64_t) -1, .memory_high = CGROUP_LIMIT_MAX, .memory_max = CGROUP_LIMIT_MAX, + .memory_swap_max = CGROUP_LIMIT_MAX, .memory_limit = (uint64_t) -1, .cpu_usage_nsec = (uint64_t) -1, .tasks_current = (uint64_t) -1, |