diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml
index d4c8fa70919..0551d750269 100644
--- a/man/systemd.resource-control.xml
+++ b/man/systemd.resource-control.xml
@@ -228,9 +228,11 @@
reclaimed as long as memory can be reclaimed from unprotected units.
Takes a memory size in bytes. If the value is suffixed with K, M, G or T, the specified memory size is
- parsed as Kilobytes, Megabytes, Gigabytes, or Terabytes (with the base 1024), respectively. This controls the
- memory.low control group attribute. For details about this control group attribute, see
- cgroup-v2.txt.
+ parsed as Kilobytes, Megabytes, Gigabytes, or Terabytes (with the base 1024), respectively. Alternatively, a
+ percentage value may be specified, which is taken relative to the installed physical memory on the
+ system. This controls the memory.low control group attribute. For details about this
+ control group attribute, see cgroup-v2.txt.
Implies MemoryAccounting=true.
@@ -247,7 +249,9 @@
aggressively in such cases. This is the main mechanism to control memory usage of a unit.
Takes a memory size in bytes. If the value is suffixed with K, M, G or T, the specified memory size is
- parsed as Kilobytes, Megabytes, Gigabytes, or Terabytes (with the base 1024), respectively. If assigned the
+ parsed as Kilobytes, Megabytes, Gigabytes, or Terabytes (with the base 1024), respectively. Alternatively, a
+ percentage value may be specified, which is taken relative to the installed physical memory on the
+ system. If assigned the
special value infinity, no memory limit is applied. This controls the
memory.high control group attribute. For details about this control group attribute, see
cgroup-v2.txt.
@@ -268,8 +272,9 @@
last line of defense.
Takes a memory size in bytes. If the value is suffixed with K, M, G or T, the specified memory size is
- parsed as Kilobytes, Megabytes, Gigabytes, or Terabytes (with the base 1024), respectively. If assigned the
- special value infinity, no memory limit is applied. This controls the
+ parsed as Kilobytes, Megabytes, Gigabytes, or Terabytes (with the base 1024), respectively. Alternatively, a
+ percentage value may be specified, which is taken relative to the installed physical memory on the system. If
+ assigned the special value infinity, no memory limit is applied. This controls the
memory.max control group attribute. For details about this control group attribute, see
cgroup-v2.txt.
@@ -284,17 +289,14 @@
MemoryLimit=bytes
- Specify the limit on maximum memory usage of the
- executed processes. The limit specifies how much process and
- kernel memory can be used by tasks in this unit. Takes a
- memory size in bytes. If the value is suffixed with K, M, G
- or T, the specified memory size is parsed as Kilobytes,
- Megabytes, Gigabytes, or Terabytes (with the base 1024),
- respectively. If assigned the special value
- infinity, no memory limit is applied. This
- controls the memory.limit_in_bytes
- control group attribute. For details about this control
- group attribute, see Specify the limit on maximum memory usage of the executed processes. The limit specifies how much
+ process and kernel memory can be used by tasks in this unit. Takes a memory size in bytes. If the value is
+ suffixed with K, M, G or T, the specified memory size is parsed as Kilobytes, Megabytes, Gigabytes, or
+ Terabytes (with the base 1024), respectively. Alternatively, a percentage value may be specified, which is
+ taken relative to the installed physical memory on the system. If assigned the special value
+ infinity, no memory limit is applied. This controls the
+ memory.limit_in_bytes control group attribute. For details about this control group
+ attribute, see memory.txt.
Implies MemoryAccounting=true.
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index fe60bee7891..05852cc7e3e 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -2812,9 +2812,19 @@ int config_parse_memory_limit(
int r;
if (!isempty(rvalue) && !streq(rvalue, "infinity")) {
- 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);
+
+ r = parse_percent(rvalue);
+ if (r < 0) {
+ r = parse_size(rvalue, 1024, &bytes);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Memory limit '%s' invalid. Ignoring.", rvalue);
+ return 0;
+ }
+ } else
+ bytes = (((physical_memory() / page_size()) * (uint64_t) r) / 100) * page_size();
+
+ if (bytes < 1) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Memory limit '%s' too small. Ignoring.", rvalue);
return 0;
}
}