systemd/5006-cgroup-Add-EffectiveMemoryMax-EffectiveMemoryHigh-an.patch
Franck Bui ebea3f9a92 - Add patches that implement [jsc#PED-5659]
5003-cgroup-rename-TasksMax-structure-to-CGroupTasksMax.patch
  5004-bus-print-properties-ignore-CGROUP_LIMIT_MAX-for-Mem.patch
  5005-bus-print-properties-prettify-more-unset-properties.patch
  5006-cgroup-Add-EffectiveMemoryMax-EffectiveMemoryHigh-an.patch
  5007-test-Convert-rlimit-test-to-subtest-of-generic-limit.patch
  5008-test-Add-effective-cgroup-limits-testing.patch
  5009-cgroup-Restrict-effective-limits-with-global-resourc.patch
  5010-cgroup-Rename-effective-limits-internal-table.patch
  They are temporarily put in quarantine to get broader testing but should be
  eventually moved to the git repo.

OBS-URL: https://build.opensuse.org/package/show/Base:System/systemd?expand=0&rev=1485
2024-01-23 13:52:53 +00:00

608 lines
28 KiB
Diff

From 9c86b2c20823dce7f8303648f7e8a8d76342d1d0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michal=20Koutn=C3=BD?= <mkoutny@suse.com>
Date: Tue, 23 Jan 2024 11:30:17 +0100
Subject: [PATCH 5006/5011] cgroup: Add EffectiveMemoryMax=,
EffectiveMemoryHigh= and EffectiveTasksMax= properties
Users become perplexed when they run their workload in a unit with no
explicit limits configured (moreover, listing the limit property would
even show it's infinity) but they experience unexpected resource
limitation.
The memory and pid limits come as the most visible, therefore add new
unit read-only properties:
- EffectiveMemoryMax=,
- EffectiveMemoryHigh=,
- EffectiveTasksMax=.
These properties represent the most stringent limit systemd is aware of
for the given unit -- and that is typically(*) the effective value.
Implement the properties by simply traversing all parents in the
leaf-slice tree and picking the minimum value. Note that effective
limits are thus defined even for units that don't enable explicit
accounting (because of the hierarchy).
(*) The evasive case is when systemd runs in a cgroupns and cannot
reason about outer setup. Complete solution would need kernel support.
(cherry picked from commit 4fb0d2dc140c9a2c01c236d2a8dc09a44157e896)
[mkoutny: adjust context, drop unapplicable XML]
[mkoutny: fixes jsc#PED-5659]
---
man/org.freedesktop.systemd1.xml | 108 ++++++++++++++++++++++++++++++
man/systemd.resource-control.xml | 11 ++-
src/core/cgroup.c | 48 +++++++++++++
src/core/cgroup.h | 13 ++++
src/core/dbus-unit.c | 25 +++++++
src/shared/bus-print-properties.c | 6 +-
6 files changed, 206 insertions(+), 5 deletions(-)
diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml
index 2e357539fb..02db33626d 100644
--- a/man/org.freedesktop.systemd1.xml
+++ b/man/org.freedesktop.systemd1.xml
@@ -2716,6 +2716,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryAvailable = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t EffectiveMemoryMax = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t EffectiveMemoryHigh = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUUsageNSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay EffectiveCPUs = [...];
@@ -2724,6 +2728,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t TasksCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t EffectiveTasksMax = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressPackets = ...;
@@ -3335,6 +3341,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<!--property MemoryCurrent is not documented!-->
+ <!--property EffectiveMemoryMax is not documented!-->
+
+ <!--property EffectiveMemoryHigh is not documented!-->
+
<!--property CPUUsageNSec is not documented!-->
<!--property EffectiveCPUs is not documented!-->
@@ -3343,6 +3353,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<!--property TasksCurrent is not documented!-->
+ <!--property EffectiveTasksMax is not documented!-->
+
<!--property IPIngressBytes is not documented!-->
<!--property IPIngressPackets is not documented!-->
@@ -3963,6 +3975,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<variablelist class="dbus-property" generated="True" extra-ref="MemoryAvailable"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="EffectiveMemoryMax"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="EffectiveMemoryHigh"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="CPUUsageNSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="EffectiveCPUs"/>
@@ -3971,6 +3987,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<variablelist class="dbus-property" generated="True" extra-ref="TasksCurrent"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="EffectiveTasksMax"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="IPIngressBytes"/>
<variablelist class="dbus-property" generated="True" extra-ref="IPIngressPackets"/>
@@ -4748,6 +4766,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryAvailable = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t EffectiveMemoryMax = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t EffectiveMemoryHigh = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUUsageNSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay EffectiveCPUs = [...];
@@ -4756,6 +4778,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t TasksCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t EffectiveTasksMax = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressPackets = ...;
@@ -5377,6 +5401,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<!--property MemoryCurrent is not documented!-->
+ <!--property EffectiveMemoryMax is not documented!-->
+
+ <!--property EffectiveMemoryHigh is not documented!-->
+
<!--property CPUUsageNSec is not documented!-->
<!--property EffectiveCPUs is not documented!-->
@@ -5385,6 +5413,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<!--property TasksCurrent is not documented!-->
+ <!--property EffectiveTasksMax is not documented!-->
+
<!--property IPIngressBytes is not documented!-->
<!--property IPIngressPackets is not documented!-->
@@ -5983,6 +6013,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<variablelist class="dbus-property" generated="True" extra-ref="MemoryAvailable"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="EffectiveMemoryMax"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="EffectiveMemoryHigh"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="CPUUsageNSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="EffectiveCPUs"/>
@@ -5991,6 +6025,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<variablelist class="dbus-property" generated="True" extra-ref="TasksCurrent"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="EffectiveTasksMax"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="IPIngressBytes"/>
<variablelist class="dbus-property" generated="True" extra-ref="IPIngressPackets"/>
@@ -6643,6 +6679,10 @@ node /org/freedesktop/systemd1/unit/home_2emount {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryAvailable = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t EffectiveMemoryMax = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t EffectiveMemoryHigh = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUUsageNSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay EffectiveCPUs = [...];
@@ -6651,6 +6691,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t TasksCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t EffectiveTasksMax = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressPackets = ...;
@@ -7200,6 +7242,10 @@ node /org/freedesktop/systemd1/unit/home_2emount {
<!--property MemoryCurrent is not documented!-->
+ <!--property EffectiveMemoryMax is not documented!-->
+
+ <!--property EffectiveMemoryHigh is not documented!-->
+
<!--property CPUUsageNSec is not documented!-->
<!--property EffectiveCPUs is not documented!-->
@@ -7208,6 +7254,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
<!--property TasksCurrent is not documented!-->
+ <!--property EffectiveTasksMax is not documented!-->
+
<!--property IPIngressBytes is not documented!-->
<!--property IPIngressPackets is not documented!-->
@@ -7724,6 +7772,10 @@ node /org/freedesktop/systemd1/unit/home_2emount {
<variablelist class="dbus-property" generated="True" extra-ref="MemoryAvailable"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="EffectiveMemoryMax"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="EffectiveMemoryHigh"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="CPUUsageNSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="EffectiveCPUs"/>
@@ -7732,6 +7784,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
<variablelist class="dbus-property" generated="True" extra-ref="TasksCurrent"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="EffectiveTasksMax"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="IPIngressBytes"/>
<variablelist class="dbus-property" generated="True" extra-ref="IPIngressPackets"/>
@@ -8511,6 +8565,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryAvailable = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t EffectiveMemoryMax = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t EffectiveMemoryHigh = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUUsageNSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay EffectiveCPUs = [...];
@@ -8519,6 +8577,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t TasksCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t EffectiveTasksMax = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressPackets = ...;
@@ -9054,6 +9114,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
<!--property MemoryCurrent is not documented!-->
+ <!--property EffectiveMemoryMax is not documented!-->
+
+ <!--property EffectiveMemoryHigh is not documented!-->
+
<!--property CPUUsageNSec is not documented!-->
<!--property EffectiveCPUs is not documented!-->
@@ -9062,6 +9126,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
<!--property TasksCurrent is not documented!-->
+ <!--property EffectiveTasksMax is not documented!-->
+
<!--property IPIngressBytes is not documented!-->
<!--property IPIngressPackets is not documented!-->
@@ -9564,6 +9630,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
<variablelist class="dbus-property" generated="True" extra-ref="MemoryAvailable"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="EffectiveMemoryMax"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="EffectiveMemoryHigh"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="CPUUsageNSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="EffectiveCPUs"/>
@@ -9572,6 +9642,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
<variablelist class="dbus-property" generated="True" extra-ref="TasksCurrent"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="EffectiveTasksMax"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="IPIngressBytes"/>
<variablelist class="dbus-property" generated="True" extra-ref="IPIngressPackets"/>
@@ -10210,6 +10282,10 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryAvailable = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t EffectiveMemoryMax = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t EffectiveMemoryHigh = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUUsageNSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay EffectiveCPUs = [...];
@@ -10218,6 +10294,8 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t TasksCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t EffectiveTasksMax = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressPackets = ...;
@@ -10381,6 +10459,10 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
<!--property MemoryCurrent is not documented!-->
+ <!--property EffectiveMemoryMax is not documented!-->
+
+ <!--property EffectiveMemoryHigh is not documented!-->
+
<!--property CPUUsageNSec is not documented!-->
<!--property EffectiveCPUs is not documented!-->
@@ -10389,6 +10471,8 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
<!--property TasksCurrent is not documented!-->
+ <!--property EffectiveTasksMax is not documented!-->
+
<!--property IPIngressBytes is not documented!-->
<!--property IPIngressPackets is not documented!-->
@@ -10557,6 +10641,10 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
<variablelist class="dbus-property" generated="True" extra-ref="MemoryAvailable"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="EffectiveMemoryMax"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="EffectiveMemoryHigh"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="CPUUsageNSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="EffectiveCPUs"/>
@@ -10565,6 +10653,8 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
<variablelist class="dbus-property" generated="True" extra-ref="TasksCurrent"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="EffectiveTasksMax"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="IPIngressBytes"/>
<variablelist class="dbus-property" generated="True" extra-ref="IPIngressPackets"/>
@@ -10759,6 +10849,10 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryAvailable = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t EffectiveMemoryMax = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t EffectiveMemoryHigh = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUUsageNSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay EffectiveCPUs = [...];
@@ -10767,6 +10861,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t TasksCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t EffectiveTasksMax = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressPackets = ...;
@@ -10950,6 +11046,10 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
<!--property MemoryCurrent is not documented!-->
+ <!--property EffectiveMemoryMax is not documented!-->
+
+ <!--property EffectiveMemoryHigh is not documented!-->
+
<!--property CPUUsageNSec is not documented!-->
<!--property EffectiveCPUs is not documented!-->
@@ -10958,6 +11058,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
<!--property TasksCurrent is not documented!-->
+ <!--property EffectiveTasksMax is not documented!-->
+
<!--property IPIngressBytes is not documented!-->
<!--property IPIngressPackets is not documented!-->
@@ -11156,6 +11258,10 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
<variablelist class="dbus-property" generated="True" extra-ref="MemoryAvailable"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="EffectiveMemoryMax"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="EffectiveMemoryHigh"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="CPUUsageNSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="EffectiveCPUs"/>
@@ -11164,6 +11270,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
<variablelist class="dbus-property" generated="True" extra-ref="TasksCurrent"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="EffectiveTasksMax"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="IPIngressBytes"/>
<variablelist class="dbus-property" generated="True" extra-ref="IPIngressPackets"/>
diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml
index 3c17efbe16..5b7900af87 100644
--- a/man/systemd.resource-control.xml
+++ b/man/systemd.resource-control.xml
@@ -392,7 +392,9 @@ CPUWeight=20 DisableControllers=cpu / \
system. If assigned the
special value <literal>infinity</literal>, no memory throttling is applied. This controls the
<literal>memory.high</literal> control group attribute. For details about this control group attribute, see
- <ulink url="https://docs.kernel.org/admin-guide/cgroup-v2.html#memory-interface-files">Memory Interface Files</ulink>.</para>
+ <ulink url="https://docs.kernel.org/admin-guide/cgroup-v2.html#memory-interface-files">Memory Interface Files</ulink>.
+ The effective configuration is reported as <varname>EffectiveMemoryHigh=</varname>
+ (see also <varname>EffectiveMemoryMax=</varname>).</para>
<para>While <varname>StartupMemoryHigh=</varname> applies to the startup and shutdown phases of the system,
<varname>MemoryHigh=</varname> applies to normal runtime of the system, and if the former is not set also to
@@ -418,7 +420,9 @@ CPUWeight=20 DisableControllers=cpu / \
percentage value may be specified, which is taken relative to the installed physical memory on the system. If
assigned the special value <literal>infinity</literal>, no memory limit is applied. This controls the
<literal>memory.max</literal> control group attribute. For details about this control group attribute, see
- <ulink url="https://docs.kernel.org/admin-guide/cgroup-v2.html#memory-interface-files">Memory Interface Files</ulink>.</para>
+ <ulink url="https://docs.kernel.org/admin-guide/cgroup-v2.html#memory-interface-files">Memory Interface Files</ulink>.
+ The effective configuration is reported as <varname>EffectiveMemoryMax=</varname> (the value is
+ the most stringent limit of the unit and parent slices).</para>
<para>While <varname>StartupMemoryMax=</varname> applies to the startup and shutdown phases of the system,
<varname>MemoryMax=</varname> applies to normal runtime of the system, and if the former is not set also to
@@ -534,7 +538,8 @@ CPUWeight=20 DisableControllers=cpu / \
limit is applied. This controls the <literal>pids.max</literal> control group attribute. For
details about this control group attribute, the
<ulink url="https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html#pid">pids controller
- </ulink>.</para>
+ </ulink>.
+ The effective configuration is reported as <varname>EffectiveTasksMax=</varname>.</para>
<para>The system default for this setting may be controlled with
<varname>DefaultTasksMax=</varname> in
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 5b7205a92e..0842036559 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -4000,6 +4000,46 @@ int unit_get_ip_accounting(
return r;
}
+static uint64_t unit_get_effective_limit_one(Unit *u, CGroupLimitType type) {
+ CGroupContext *cc;
+
+ assert(u);
+ assert(UNIT_HAS_CGROUP_CONTEXT(u));
+
+ cc = unit_get_cgroup_context(u);
+ switch (type) {
+ /* Note: on legacy/hybrid hierarchies memory_max stays CGROUP_LIMIT_MAX unless configured
+ * explicitly. Effective value of MemoryLimit= (cgroup v1) is not implemented. */
+ case CGROUP_LIMIT_MEMORY_MAX:
+ return cc->memory_max;
+ case CGROUP_LIMIT_MEMORY_HIGH:
+ return cc->memory_high;
+ case CGROUP_LIMIT_TASKS_MAX:
+ return cgroup_tasks_max_resolve(&cc->tasks_max);
+ default:
+ assert_not_reached();
+ }
+}
+
+int unit_get_effective_limit(Unit *u, CGroupLimitType type, uint64_t *ret) {
+ uint64_t infimum;
+
+ assert(u);
+ assert(ret);
+ assert(type >= 0);
+ assert(type < _CGROUP_LIMIT_TYPE_MAX);
+
+ if (!UNIT_HAS_CGROUP_CONTEXT(u))
+ return -EINVAL;
+
+ infimum = unit_get_effective_limit_one(u, type);
+ for (Unit *slice = UNIT_GET_SLICE(u); slice; slice = UNIT_GET_SLICE(slice))
+ infimum = MIN(infimum, unit_get_effective_limit_one(slice, type));
+
+ *ret = infimum;
+ return 0;
+}
+
static int unit_get_io_accounting_raw(Unit *u, uint64_t ret[static _CGROUP_IO_ACCOUNTING_METRIC_MAX]) {
static const char *const field_names[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = {
[CGROUP_IO_READ_BYTES] = "rbytes=",
@@ -4418,3 +4458,11 @@ static const char* const cgroup_pressure_watch_table[_CGROUP_PRESSURE_WATCH_MAX]
};
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(cgroup_pressure_watch, CGroupPressureWatch, CGROUP_PRESSURE_WATCH_ON);
+
+static const char *const cgroup_limit_type_table[_CGROUP_LIMIT_TYPE_MAX] = {
+ [CGROUP_LIMIT_MEMORY_MAX] = "EffectiveMemoryMax",
+ [CGROUP_LIMIT_MEMORY_HIGH] = "EffectiveMemoryHigh",
+ [CGROUP_LIMIT_TASKS_MAX] = "EffectiveTasksMax",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(cgroup_limit_type, CGroupLimitType);
diff --git a/src/core/cgroup.h b/src/core/cgroup.h
index 486957b545..a19a2fffa3 100644
--- a/src/core/cgroup.h
+++ b/src/core/cgroup.h
@@ -245,6 +245,15 @@ typedef enum CGroupIOAccountingMetric {
_CGROUP_IO_ACCOUNTING_METRIC_INVALID = -EINVAL,
} CGroupIOAccountingMetric;
+/* Used for limits whose value sets have infimum */
+typedef enum CGroupLimitType {
+ CGROUP_LIMIT_MEMORY_MAX,
+ CGROUP_LIMIT_MEMORY_HIGH,
+ CGROUP_LIMIT_TASKS_MAX,
+ _CGROUP_LIMIT_TYPE_MAX,
+ _CGROUP_LIMIT_INVALID = -EINVAL,
+} CGroupLimitType;
+
typedef struct Unit Unit;
typedef struct Manager Manager;
@@ -337,6 +346,7 @@ int unit_get_tasks_current(Unit *u, uint64_t *ret);
int unit_get_cpu_usage(Unit *u, nsec_t *ret);
int unit_get_io_accounting(Unit *u, CGroupIOAccountingMetric metric, bool allow_cache, uint64_t *ret);
int unit_get_ip_accounting(Unit *u, CGroupIPAccountingMetric metric, uint64_t *ret);
+int unit_get_effective_limit(Unit *u, CGroupLimitType type, uint64_t *ret);
int unit_reset_cpu_accounting(Unit *u);
int unit_reset_ip_accounting(Unit *u);
@@ -378,3 +388,6 @@ FreezerAction freezer_action_from_string(const char *s) _pure_;
const char* cgroup_pressure_watch_to_string(CGroupPressureWatch a) _const_;
CGroupPressureWatch cgroup_pressure_watch_from_string(const char *s) _pure_;
+
+const char* cgroup_limit_type_to_string(CGroupLimitType m) _const_;
+CGroupLimitType cgroup_limit_type_from_string(const char *s) _pure_;
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index ed376cec87..b4509a990e 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -1438,6 +1438,28 @@ static int property_get_io_counter(
return sd_bus_message_append(reply, "t", value);
}
+static int property_get_effective_limit(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ uint64_t value = CGROUP_LIMIT_MAX;
+ Unit *u = ASSERT_PTR(userdata);
+ ssize_t type;
+
+ assert(bus);
+ assert(reply);
+ assert(property);
+
+ assert_se((type = cgroup_limit_type_from_string(property)) >= 0);
+ (void) unit_get_effective_limit(u, type, &value);
+ return sd_bus_message_append(reply, "t", value);
+}
+
int bus_unit_method_attach_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
@@ -1557,10 +1579,13 @@ const sd_bus_vtable bus_unit_cgroup_vtable[] = {
SD_BUS_PROPERTY("ControlGroupId", "t", NULL, offsetof(Unit, cgroup_id), 0),
SD_BUS_PROPERTY("MemoryCurrent", "t", property_get_current_memory, 0, 0),
SD_BUS_PROPERTY("MemoryAvailable", "t", property_get_available_memory, 0, 0),
+ SD_BUS_PROPERTY("EffectiveMemoryMax", "t", property_get_effective_limit, 0, 0),
+ SD_BUS_PROPERTY("EffectiveMemoryHigh", "t", property_get_effective_limit, 0, 0),
SD_BUS_PROPERTY("CPUUsageNSec", "t", property_get_cpu_usage, 0, 0),
SD_BUS_PROPERTY("EffectiveCPUs", "ay", property_get_cpuset_cpus, 0, 0),
SD_BUS_PROPERTY("EffectiveMemoryNodes", "ay", property_get_cpuset_mems, 0, 0),
SD_BUS_PROPERTY("TasksCurrent", "t", property_get_current_tasks, 0, 0),
+ SD_BUS_PROPERTY("EffectiveTasksMax", "t", property_get_effective_limit, 0, 0),
SD_BUS_PROPERTY("IPIngressBytes", "t", property_get_ip_counter, 0, 0),
SD_BUS_PROPERTY("IPIngressPackets", "t", property_get_ip_counter, 0, 0),
SD_BUS_PROPERTY("IPEgressBytes", "t", property_get_ip_counter, 0, 0),
diff --git a/src/shared/bus-print-properties.c b/src/shared/bus-print-properties.c
index f74d8994ad..62bbc598bb 100644
--- a/src/shared/bus-print-properties.c
+++ b/src/shared/bus-print-properties.c
@@ -164,9 +164,11 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
bus_print_property_value(name, expected_value, flags, "[not set]");
- else if ((ENDSWITH_SET(name, "MemoryLow", "MemoryMin", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryZSwapMax", "MemoryLimit") &&
+ else if ((ENDSWITH_SET(name, "MemoryLow", "MemoryMin",
+ "MemoryHigh", "MemoryMax",
+ "MemorySwapMax", "MemoryZSwapMax", "MemoryLimit") &&
u == CGROUP_LIMIT_MAX) ||
- (STR_IN_SET(name, "TasksMax", "DefaultTasksMax") && u == UINT64_MAX) ||
+ (endswith(name, "TasksMax") && u == UINT64_MAX) ||
(startswith(name, "Limit") && u == UINT64_MAX) ||
(startswith(name, "DefaultLimit") && u == UINT64_MAX))
--
2.35.3