diff options
-rw-r--r-- | man/org.freedesktop.systemd1.xml | 126 | ||||
-rw-r--r-- | man/systemd.resource-control.xml | 11 | ||||
-rw-r--r-- | src/core/cgroup.c | 59 | ||||
-rw-r--r-- | src/core/cgroup.h | 13 | ||||
-rw-r--r-- | src/core/dbus-unit.c | 25 | ||||
-rw-r--r-- | src/shared/bus-print-properties.c | 6 | ||||
-rwxr-xr-x | test/units/testsuite-05.effective-limit.sh | 68 | ||||
-rwxr-xr-x | test/units/testsuite-05.rlimit.sh | 25 | ||||
-rw-r--r-- | test/units/testsuite-05.service | 2 | ||||
-rwxr-xr-x | test/units/testsuite-05.sh | 22 | ||||
-rwxr-xr-x | test/units/util.sh | 9 |
11 files changed, 341 insertions, 25 deletions
diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml index 1bdff502ca..878bd0d99d 100644 --- a/man/org.freedesktop.systemd1.xml +++ b/man/org.freedesktop.systemd1.xml @@ -2806,6 +2806,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 = [...]; @@ -2814,6 +2818,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 = ...; @@ -3439,6 +3445,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { <!--property MemoryZSwapCurrent is not documented!--> + <!--property EffectiveMemoryMax is not documented!--> + + <!--property EffectiveMemoryHigh is not documented!--> + <!--property CPUUsageNSec is not documented!--> <!--property EffectiveCPUs is not documented!--> @@ -3447,6 +3457,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!--> @@ -4081,6 +4093,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"/> @@ -4089,6 +4105,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"/> @@ -4885,6 +4903,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 = [...]; @@ -4893,6 +4915,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 = ...; @@ -5528,6 +5552,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { <!--property MemoryZSwapCurrent is not documented!--> + <!--property EffectiveMemoryMax is not documented!--> + + <!--property EffectiveMemoryHigh is not documented!--> + <!--property CPUUsageNSec is not documented!--> <!--property EffectiveCPUs is not documented!--> @@ -5536,6 +5564,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!--> @@ -6152,6 +6182,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"/> @@ -6160,6 +6194,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"/> @@ -6830,6 +6866,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 = [...]; @@ -6838,6 +6878,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 = ...; @@ -7401,6 +7443,10 @@ node /org/freedesktop/systemd1/unit/home_2emount { <!--property MemoryZSwapCurrent is not documented!--> + <!--property EffectiveMemoryMax is not documented!--> + + <!--property EffectiveMemoryHigh is not documented!--> + <!--property CPUUsageNSec is not documented!--> <!--property EffectiveCPUs is not documented!--> @@ -7409,6 +7455,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!--> @@ -7939,6 +7987,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"/> @@ -7947,6 +7999,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"/> @@ -8740,6 +8794,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 = [...]; @@ -8748,6 +8806,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 = ...; @@ -9297,6 +9357,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { <!--property MemoryZSwapCurrent is not documented!--> + <!--property EffectiveMemoryMax is not documented!--> + + <!--property EffectiveMemoryHigh is not documented!--> + <!--property CPUUsageNSec is not documented!--> <!--property EffectiveCPUs is not documented!--> @@ -9305,6 +9369,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!--> @@ -9821,6 +9887,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"/> @@ -9829,6 +9899,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"/> @@ -10481,6 +10553,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 = [...]; @@ -10489,6 +10565,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 = ...; @@ -10664,6 +10742,10 @@ node /org/freedesktop/systemd1/unit/system_2eslice { <!--property MemoryZSwapCurrent is not documented!--> + <!--property EffectiveMemoryMax is not documented!--> + + <!--property EffectiveMemoryHigh is not documented!--> + <!--property CPUUsageNSec is not documented!--> <!--property EffectiveCPUs is not documented!--> @@ -10672,6 +10754,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!--> @@ -10852,6 +10936,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"/> @@ -10860,6 +10948,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"/> @@ -11066,6 +11156,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 = [...]; @@ -11074,6 +11168,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 = ...; @@ -11269,6 +11365,10 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { <!--property MemoryZSwapCurrent is not documented!--> + <!--property EffectiveMemoryMax is not documented!--> + + <!--property EffectiveMemoryHigh is not documented!--> + <!--property CPUUsageNSec is not documented!--> <!--property EffectiveCPUs is not documented!--> @@ -11277,6 +11377,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!--> @@ -11487,6 +11589,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"/> @@ -11495,6 +11601,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"/> @@ -11888,6 +11996,9 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \ <varname>MemorySwapCurrent</varname>, <varname>MemorySwapPeak</varname>, and <varname>MemoryZSwapCurrent</varname> were added in version 255.</para> + <para><varname>EffectiveMemoryHigh</varname>, + <varname>EffectiveMemoryMax</varname>, + <varname>EffectiveTasksMax</varname> were added in version 256.</para> </refsect2> <refsect2> <title>Socket Unit Objects</title> @@ -11919,6 +12030,9 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \ <varname>MemorySwapCurrent</varname>, <varname>MemorySwapPeak</varname>, and <varname>MemoryZSwapCurrent</varname> were added in version 255.</para> + <para><varname>EffectiveMemoryHigh</varname>, + <varname>EffectiveMemoryMax</varname>, + <varname>EffectiveTasksMax</varname> were added in version 256.</para> </refsect2> <refsect2> <title>Mount Unit Objects</title> @@ -11948,6 +12062,9 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \ <varname>MemorySwapCurrent</varname>, <varname>MemorySwapPeak</varname>, and <varname>MemoryZSwapCurrent</varname> were added in version 255.</para> + <para><varname>EffectiveMemoryHigh</varname>, + <varname>EffectiveMemoryMax</varname>, + <varname>EffectiveTasksMax</varname> were added in version 256.</para> </refsect2> <refsect2> <title>Swap Unit Objects</title> @@ -11977,6 +12094,9 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \ <varname>MemorySwapCurrent</varname>, <varname>MemorySwapPeak</varname>, and <varname>MemoryZSwapCurrent</varname> were added in version 255.</para> + <para><varname>EffectiveMemoryHigh</varname>, + <varname>EffectiveMemoryMax</varname>, + <varname>EffectiveTasksMax</varname> were added in version 256.</para> </refsect2> <refsect2> <title>Slice Unit Objects</title> @@ -11997,6 +12117,9 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \ <varname>MemorySwapCurrent</varname>, <varname>MemorySwapPeak</varname>, and <varname>MemoryZSwapCurrent</varname> were added in version 255.</para> + <para><varname>EffectiveMemoryHigh</varname>, + <varname>EffectiveMemoryMax</varname>, + <varname>EffectiveTasksMax</varname> were added in version 256.</para> </refsect2> <refsect2> <title>Scope Unit Objects</title> @@ -12018,6 +12141,9 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \ <varname>MemorySwapCurrent</varname>, <varname>MemorySwapPeak</varname>, and <varname>MemoryZSwapCurrent</varname> were added in version 255.</para> + <para><varname>EffectiveMemoryHigh</varname>, + <varname>EffectiveMemoryMax</varname>, + <varname>EffectiveTasksMax</varname> were added in version 256.</para> </refsect2> <refsect2> <title>Job Objects</title> diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml index 2c5785cca9..2eb6797f4c 100644 --- a/man/systemd.resource-control.xml +++ b/man/systemd.resource-control.xml @@ -409,7 +409,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 @@ -437,7 +439,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 and it is capped by physical memory).</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 @@ -563,7 +567,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 311a4197aa..411f59d55d 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -4555,6 +4555,57 @@ 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)); + + if (unit_has_name(u, SPECIAL_ROOT_SLICE)) + switch (type) { + case CGROUP_LIMIT_MEMORY_MAX: + case CGROUP_LIMIT_MEMORY_HIGH: + return physical_memory(); + case CGROUP_LIMIT_TASKS_MAX: + return system_tasks_max(); + default: + assert_not_reached(); + } + + 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=", @@ -4975,3 +5026,11 @@ static const char* const cgroup_memory_accounting_metric_table[_CGROUP_MEMORY_AC }; DEFINE_STRING_TABLE_LOOKUP(cgroup_memory_accounting_metric, CGroupMemoryAccountingMetric); + +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 ecd6759983..1d6938aa18 100644 --- a/src/core/cgroup.h +++ b/src/core/cgroup.h @@ -277,6 +277,15 @@ typedef enum CGroupMemoryAccountingMetric { _CGROUP_MEMORY_ACCOUNTING_METRIC_INVALID = -EINVAL, } CGroupMemoryAccountingMetric; +/* 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; typedef enum ManagerState ManagerState; @@ -388,6 +397,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); void unit_reset_memory_accounting_last(Unit *u); @@ -439,5 +449,8 @@ CGroupIPAccountingMetric cgroup_ip_accounting_metric_from_string(const char *s) const char* cgroup_io_accounting_metric_to_string(CGroupIOAccountingMetric m) _const_; CGroupIOAccountingMetric cgroup_io_accounting_metric_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_; + const char* cgroup_memory_accounting_metric_to_string(CGroupMemoryAccountingMetric m) _const_; CGroupMemoryAccountingMetric cgroup_memory_accounting_metric_from_string(const char *s) _pure_; diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 8b4983dcb5..3aeb85e452 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -1426,6 +1426,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; _cleanup_set_free_ Set *pids = NULL; @@ -1547,10 +1569,13 @@ const sd_bus_vtable bus_unit_cgroup_vtable[] = { SD_BUS_PROPERTY("MemorySwapPeak", "t", property_get_memory_accounting, 0, 0), SD_BUS_PROPERTY("MemoryZSwapCurrent", "t", property_get_memory_accounting, 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 6704e1ef3d..99b1cc7c70 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)) diff --git a/test/units/testsuite-05.effective-limit.sh b/test/units/testsuite-05.effective-limit.sh new file mode 100755 index 0000000000..3ff8e83140 --- /dev/null +++ b/test/units/testsuite-05.effective-limit.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: LGPL-2.1-or-later +set -eux +set -o pipefail + +# shellcheck source=test/units/util.sh +. "$(dirname "$0")"/util.sh + +pre=test05 +cat >/run/systemd/system/"$pre"alpha.slice <<EOF +[Slice] +MemoryMax=40M +MemoryHigh=40M +TasksMax=400 +EOF + +cat >/run/systemd/system/"$pre"alpha-beta.slice <<EOF +[Slice] +MemoryMax=10M +MemoryHigh=10M +TasksMax=100 +EOF + +cat >/run/systemd/system/"$pre"alpha-beta-gamma.slice <<EOF +[Slice] +MemoryMax=20M +MemoryHigh=20M +TasksMax=200 +EOF + +systemctl daemon-reload + +srv=probe.service +slc0="$pre"alpha.slice +slc="$pre"alpha-beta-gamma.slice + +systemd-run --unit "$srv" --slice "$slc" \ + -p MemoryMax=5M \ + -p MemoryHigh=5M \ + -p TasksMax=50 \ + sleep inf + +# Compare with inequality because test can run in a constrained container +assert_le "$(systemctl show -P EffectiveMemoryMax "$srv")" "5242880" +assert_le "$(systemctl show -P EffectiveMemoryHigh "$srv")" "5242880" +assert_le "$(systemctl show -P EffectiveTasksMax "$srv")" "50" + +systemctl stop "$srv" + +systemd-run --unit "$srv" --slice "$slc" \ + sleep inf + +assert_le "$(systemctl show -P EffectiveMemoryMax "$srv")" "10485760" +assert_le "$(systemctl show -P EffectiveMemoryHigh "$srv")" "10485760" +assert_le "$(systemctl show -P EffectiveTasksMax "$srv")" "100" + +systemctl set-property "$slc0" \ + MemoryMax=5M \ + MemoryHigh=5M \ + TasksMax=50 + +assert_le "$(systemctl show -P EffectiveMemoryMax "$srv")" "5242880" +assert_le "$(systemctl show -P EffectiveMemoryHigh "$srv")" "5242880" +assert_le "$(systemctl show -P EffectiveTasksMax "$srv")" "50" + +systemctl stop "$srv" + +rm -f /run/systemd/system/"$pre"* || : diff --git a/test/units/testsuite-05.rlimit.sh b/test/units/testsuite-05.rlimit.sh new file mode 100755 index 0000000000..bbf3adbe65 --- /dev/null +++ b/test/units/testsuite-05.rlimit.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: LGPL-2.1-or-later +set -eux +set -o pipefail + +P=/run/systemd/system.conf.d +mkdir $P + +cat >$P/rlimits.conf <<EOF +[Manager] +DefaultLimitNOFILE=10000:16384 +EOF + +systemctl daemon-reload + +[[ "$(systemctl show -P DefaultLimitNOFILESoft)" = "10000" ]] +[[ "$(systemctl show -P DefaultLimitNOFILE)" = "16384" ]] + +[[ "$(systemctl show -P LimitNOFILESoft testsuite-05.service)" = "10000" ]] +[[ "$(systemctl show -P LimitNOFILE testsuite-05.service)" = "16384" ]] + +# shellcheck disable=SC2016 +systemd-run --wait -t bash -c '[[ "$(ulimit -n -S)" = "10000" ]]' +# shellcheck disable=SC2016 +systemd-run --wait -t bash -c '[[ "$(ulimit -n -H)" = "16384" ]]' diff --git a/test/units/testsuite-05.service b/test/units/testsuite-05.service index ab72d8fe27..cf32accb8c 100644 --- a/test/units/testsuite-05.service +++ b/test/units/testsuite-05.service @@ -1,6 +1,6 @@ # SPDX-License-Identifier: LGPL-2.1-or-later [Unit] -Description=TEST-05-RLIMITS +Description=TEST-05-LIMITS [Service] ExecStartPre=rm -f /failed /testok diff --git a/test/units/testsuite-05.sh b/test/units/testsuite-05.sh index 870845d14b..9c2a033aa9 100755 --- a/test/units/testsuite-05.sh +++ b/test/units/testsuite-05.sh @@ -3,25 +3,9 @@ set -eux set -o pipefail -P=/run/systemd/system.conf.d -mkdir $P +# shellcheck source=test/units/test-control.sh +. "$(dirname "$0")"/test-control.sh -cat >$P/rlimits.conf <<EOF -[Manager] -DefaultLimitNOFILE=10000:16384 -EOF - -systemctl daemon-reload - -[[ "$(systemctl show -P DefaultLimitNOFILESoft)" = "10000" ]] -[[ "$(systemctl show -P DefaultLimitNOFILE)" = "16384" ]] - -[[ "$(systemctl show -P LimitNOFILESoft testsuite-05.service)" = "10000" ]] -[[ "$(systemctl show -P LimitNOFILE testsuite-05.service)" = "16384" ]] - -# shellcheck disable=SC2016 -systemd-run --wait -t bash -c '[[ "$(ulimit -n -S)" = "10000" ]]' -# shellcheck disable=SC2016 -systemd-run --wait -t bash -c '[[ "$(ulimit -n -H)" = "16384" ]]' +run_subtests touch /testok diff --git a/test/units/util.sh b/test/units/util.sh index a18c8980cf..66f9c73ba6 100755 --- a/test/units/util.sh +++ b/test/units/util.sh @@ -28,6 +28,15 @@ assert_eq() {( fi )} +assert_le() {( + set +ex + + if [[ "${1:?}" -gt "${2:?}" ]]; then + echo "FAIL: '$1' > '$2'" >&2 + exit 1 + fi +)} + assert_in() {( set +ex |