core: Add support for CPU pressure notifications

Works the same way as memory pressure notifications. Code is refactored
to work on enum arrays to reduce duplication.
This commit is contained in:
Daan De Meyer
2026-04-09 22:47:10 +02:00
committed by Daan De Meyer
parent b3bb4fefde
commit 316d17fcbd
29 changed files with 561 additions and 200 deletions
+99 -1
View File
@@ -552,6 +552,10 @@ node /org/freedesktop/systemd1 {
readonly t DefaultMemoryPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DefaultMemoryPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t DefaultCPUPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DefaultCPUPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t TimerSlackNSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@@ -793,6 +797,10 @@ node /org/freedesktop/systemd1 {
<!--property DefaultMemoryPressureWatch is not documented!-->
<!--property DefaultCPUPressureThresholdUSec is not documented!-->
<!--property DefaultCPUPressureWatch is not documented!-->
<!--property TimerSlackNSec is not documented!-->
<!--property DefaultOOMPolicy is not documented!-->
@@ -1243,6 +1251,10 @@ node /org/freedesktop/systemd1 {
<variablelist class="dbus-property" generated="True" extra-ref="DefaultMemoryPressureWatch"/>
<variablelist class="dbus-property" generated="True" extra-ref="DefaultCPUPressureThresholdUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="DefaultCPUPressureWatch"/>
<variablelist class="dbus-property" generated="True" extra-ref="TimerSlackNSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="DefaultOOMPolicy"/>
@@ -3066,6 +3078,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s CPUPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiss) NFTSet = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b CoredumpReceive = ...;
@@ -3735,6 +3751,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<!--property MemoryPressureThresholdUSec is not documented!-->
<!--property CPUPressureWatch is not documented!-->
<!--property CPUPressureThresholdUSec is not documented!-->
<!--property NFTSet is not documented!-->
<!--property CoredumpReceive is not documented!-->
@@ -4427,6 +4447,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<variablelist class="dbus-property" generated="True" extra-ref="MemoryPressureThresholdUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUPressureWatch"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUPressureThresholdUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="NFTSet"/>
<variablelist class="dbus-property" generated="True" extra-ref="CoredumpReceive"/>
@@ -5326,6 +5350,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s CPUPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiss) NFTSet = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b CoredumpReceive = ...;
@@ -6011,6 +6039,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<!--property MemoryPressureThresholdUSec is not documented!-->
<!--property CPUPressureWatch is not documented!-->
<!--property CPUPressureThresholdUSec is not documented!-->
<!--property NFTSet is not documented!-->
<!--property CoredumpReceive is not documented!-->
@@ -6677,6 +6709,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<variablelist class="dbus-property" generated="True" extra-ref="MemoryPressureThresholdUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUPressureWatch"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUPressureThresholdUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="NFTSet"/>
<variablelist class="dbus-property" generated="True" extra-ref="CoredumpReceive"/>
@@ -7399,6 +7435,10 @@ node /org/freedesktop/systemd1/unit/home_2emount {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s CPUPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiss) NFTSet = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b CoredumpReceive = ...;
@@ -8008,6 +8048,10 @@ node /org/freedesktop/systemd1/unit/home_2emount {
<!--property MemoryPressureThresholdUSec is not documented!-->
<!--property CPUPressureWatch is not documented!-->
<!--property CPUPressureThresholdUSec is not documented!-->
<!--property NFTSet is not documented!-->
<!--property CoredumpReceive is not documented!-->
@@ -8582,6 +8626,10 @@ node /org/freedesktop/systemd1/unit/home_2emount {
<variablelist class="dbus-property" generated="True" extra-ref="MemoryPressureThresholdUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUPressureWatch"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUPressureThresholdUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="NFTSet"/>
<variablelist class="dbus-property" generated="True" extra-ref="CoredumpReceive"/>
@@ -9437,6 +9485,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s CPUPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiss) NFTSet = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b CoredumpReceive = ...;
@@ -10028,6 +10080,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
<!--property MemoryPressureThresholdUSec is not documented!-->
<!--property CPUPressureWatch is not documented!-->
<!--property CPUPressureThresholdUSec is not documented!-->
<!--property NFTSet is not documented!-->
<!--property CoredumpReceive is not documented!-->
@@ -10584,6 +10640,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
<variablelist class="dbus-property" generated="True" extra-ref="MemoryPressureThresholdUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUPressureWatch"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUPressureThresholdUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="NFTSet"/>
<variablelist class="dbus-property" generated="True" extra-ref="CoredumpReceive"/>
@@ -11292,6 +11352,10 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s CPUPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiss) NFTSet = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b CoredumpReceive = ...;
@@ -11465,6 +11529,10 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
<!--property MemoryPressureThresholdUSec is not documented!-->
<!--property CPUPressureWatch is not documented!-->
<!--property CPUPressureThresholdUSec is not documented!-->
<!--property NFTSet is not documented!-->
<!--property CoredumpReceive is not documented!-->
@@ -11653,6 +11721,10 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
<variablelist class="dbus-property" generated="True" extra-ref="MemoryPressureThresholdUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUPressureWatch"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUPressureThresholdUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="NFTSet"/>
<variablelist class="dbus-property" generated="True" extra-ref="CoredumpReceive"/>
@@ -11864,6 +11936,10 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s CPUPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiss) NFTSet = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b CoredumpReceive = ...;
@@ -12051,6 +12127,10 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
<!--property MemoryPressureThresholdUSec is not documented!-->
<!--property CPUPressureWatch is not documented!-->
<!--property CPUPressureThresholdUSec is not documented!-->
<!--property NFTSet is not documented!-->
<!--property CoredumpReceive is not documented!-->
@@ -12263,6 +12343,10 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
<variablelist class="dbus-property" generated="True" extra-ref="MemoryPressureThresholdUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUPressureWatch"/>
<variablelist class="dbus-property" generated="True" extra-ref="CPUPressureThresholdUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="NFTSet"/>
<variablelist class="dbus-property" generated="True" extra-ref="CoredumpReceive"/>
@@ -12475,7 +12559,9 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
<function>RemoveSubgroupFromUnit()</function>, and
<function>KillUnitSubgroup()</function> were added in version 258.</para>
<para><varname>TransactionsWithOrderingCycle</varname> was added in version 259.</para>
<para><varname>DefaultMemoryZSwapWriteback</varname> was added in version 261.</para>
<para><varname>DefaultMemoryZSwapWriteback</varname>,
<varname>DefaultCPUPressureThresholdUSec</varname> and
<varname>DefaultCPUPressureWatch</varname> were added in version 261.</para>
</refsect2>
<refsect2>
<title>Unit Objects</title>
@@ -12567,6 +12653,8 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
<varname>ExecReloadPostEx</varname> were added in version 259.</para>
<para><varname>BindNetworkInterface</varname>, <varname>MemoryTHP</varname>,
<varname>RefreshOnReload</varname>, and <varname>RootMStack</varname> were added in version 260.</para>
<para><varname>CPUPressureThresholdUSec</varname> and
<varname>CPUPressureWatch</varname> were added in version 261.</para>
</refsect2>
<refsect2>
<title>Socket Unit Objects</title>
@@ -12637,6 +12725,8 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
<varname>ManagedOOMKills</varname> were added in 259.</para>
<para><varname>BindNetworkInterface</varname> <varname>MemoryTHP</varname>, and
<varname>RootMStack</varname> were added in version 260.</para>
<para><varname>CPUPressureThresholdUSec</varname> and
<varname>CPUPressureWatch</varname> were added in version 261.</para>
</refsect2>
<refsect2>
<title>Mount Unit Objects</title>
@@ -12702,6 +12792,8 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
<varname>ManagedOOMKills</varname> were added in 259.</para>
<para><varname>BindNetworkInterface</varname> <varname>MemoryTHP</varname>, and
<varname>RootMStack</varname> were added in version 260.</para>
<para><varname>CPUPressureThresholdUSec</varname> and
<varname>CPUPressureWatch</varname> were added in version 261.</para>
</refsect2>
<refsect2>
<title>Swap Unit Objects</title>
@@ -12765,6 +12857,8 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
<varname>ManagedOOMKills</varname> were added in 259.</para>
<para><varname>BindNetworkInterface</varname>, <varname>MemoryTHP</varname>, and
<varname>RootMStack</varname> were added in version 260.</para>
<para><varname>CPUPressureThresholdUSec</varname> and
<varname>CPUPressureWatch</varname> were added in version 261.</para>
</refsect2>
<refsect2>
<title>Slice Unit Objects</title>
@@ -12798,6 +12892,8 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
<para><varname>OOMKills</varname>, and
<varname>ManagedOOMKills</varname> were added in 259.</para>
<para><varname>BindNetworkInterface</varname> was added in version 260.</para>
<para><varname>CPUPressureThresholdUSec</varname> and
<varname>CPUPressureWatch</varname> were added in version 261.</para>
</refsect2>
<refsect2>
<title>Scope Unit Objects</title>
@@ -12829,6 +12925,8 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
<para><varname>OOMKills</varname>, and
<varname>ManagedOOMKills</varname> were added in 259.</para>
<para><varname>BindNetworkInterface</varname> was added in version 260.</para>
<para><varname>CPUPressureThresholdUSec</varname> and
<varname>CPUPressureWatch</varname> were added in version 261.</para>
</refsect2>
<refsect2>
<title>Job Objects</title>
+14
View File
@@ -326,6 +326,20 @@
<xi:include href="version-info.xml" xpointer="v254"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>DefaultCPUPressureWatch=</varname></term>
<term><varname>DefaultCPUPressureThresholdSec=</varname></term>
<listitem><para>Configures the default settings for the per-unit
<varname>CPUPressureWatch=</varname> and <varname>CPUPressureThresholdSec=</varname>
settings. See
<citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details. Defaults to <literal>auto</literal> and <literal>200ms</literal>, respectively. This
also sets the CPU pressure monitoring threshold for the service manager itself.</para>
<xi:include href="version-info.xml" xpointer="v261"/></listitem>
</varlistentry>
</variablelist>
</refsect1>
+12
View File
@@ -4705,6 +4705,18 @@ StandardInputData=V2XigLJyZSBubyBzdHJhbmdlcnMgdG8gbG92ZQpZb3Uga25vdyB0aGUgcnVsZX
<xi:include href="version-info.xml" xpointer="v254"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>$CPU_PRESSURE_WATCH</varname></term>
<term><varname>$CPU_PRESSURE_WRITE</varname></term>
<listitem><para>If CPU pressure monitoring is enabled for this service unit, the path to watch
and the data to write into it. See <ulink url="https://systemd.io/PRESSURE">Resource Pressure
Handling</ulink> for details about these variables and the service protocol data they
convey.</para>
<xi:include href="version-info.xml" xpointer="v261"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>$FDSTORE</varname></term>
+49
View File
@@ -1657,6 +1657,55 @@ DeviceAllow=/dev/loop-control
<xi:include href="version-info.xml" xpointer="v254"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>CPUPressureWatch=</varname></term>
<listitem><para>Controls CPU pressure monitoring for invoked processes. Takes a boolean or one of
<literal>auto</literal> and <literal>skip</literal>. If <literal>no</literal>, tells the service not
to watch for CPU pressure events, by setting the <varname>$CPU_PRESSURE_WATCH</varname>
environment variable to the literal string <filename>/dev/null</filename>. If <literal>yes</literal>,
tells the service to watch for CPU pressure events. This ensures the
<filename>cpu.pressure</filename> cgroup attribute file is accessible for
reading and writing by the service's user. It then sets the <varname>$CPU_PRESSURE_WATCH</varname>
environment variable for processes invoked by the unit to the file system path to this file. The
threshold information configured with <varname>CPUPressureThresholdSec=</varname> is encoded in
the <varname>$CPU_PRESSURE_WRITE</varname> environment variable. If the <literal>auto</literal>
value is set the protocol is enabled if CPU resource controls are configured for the unit (e.g. because
<varname>CPUWeight=</varname> or <varname>CPUQuota=</varname> is set), and
disabled otherwise. If set to <literal>skip</literal> the logic is neither enabled, nor disabled and
the two environment variables are not set.</para>
<para>Note that services are free to use the two environment variables, but it is unproblematic if
they ignore them. CPU pressure handling must be implemented individually in each service, and
usually means different things for different software.</para>
<para>Services implemented using
<citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry> may use
<citerefentry><refentrytitle>sd_event_add_cpu_pressure</refentrytitle><manvolnum>3</manvolnum></citerefentry>
to watch for and handle CPU pressure events.</para>
<para>If not explicitly set, defaults to the <varname>DefaultCPUPressureWatch=</varname> setting in
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
<xi:include href="version-info.xml" xpointer="v261"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>CPUPressureThresholdSec=</varname></term>
<listitem><para>Sets the CPU pressure threshold time for CPU pressure monitor as configured via
<varname>CPUPressureWatch=</varname>. Specifies the maximum CPU stall time before a CPU
pressure event is signalled to the service, per 2s window. If not specified, defaults to the
<varname>DefaultCPUPressureThresholdSec=</varname> setting in
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
(which in turn defaults to 200ms). The specified value expects a time unit such as
<literal>ms</literal> or <literal>μs</literal>, see
<citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
details on the permitted syntax.</para>
<xi:include href="version-info.xml" xpointer="v261"/></listitem>
</varlistentry>
</variablelist>
</refsect2><refsect2><title>Coredump Control</title>
+5
View File
@@ -43,6 +43,11 @@ typedef struct PressureResourceInfo {
extern const PressureResourceInfo pressure_resource_info[_PRESSURE_RESOURCE_MAX];
static inline const PressureResourceInfo* pressure_resource_get_info(PressureResource resource) {
assert(resource >= 0 && resource < _PRESSURE_RESOURCE_MAX);
return &pressure_resource_info[resource];
}
DECLARE_STRING_TABLE_LOOKUP(pressure_resource, PressureResource);
/* Default parameters for pressure watch logic in sd-event and PID 1 */
+19 -10
View File
@@ -185,8 +185,10 @@ void cgroup_context_init(CGroupContext *c) {
* moom_mem_pressure_duration_usec is set to infinity. */
.moom_mem_pressure_duration_usec = USEC_INFINITY,
.memory_pressure_watch = _CGROUP_PRESSURE_WATCH_INVALID,
.memory_pressure_threshold_usec = USEC_INFINITY,
.pressure = {
[PRESSURE_MEMORY] = { .watch = _CGROUP_PRESSURE_WATCH_INVALID, .threshold_usec = USEC_INFINITY },
[PRESSURE_CPU] = { .watch = _CGROUP_PRESSURE_WATCH_INVALID, .threshold_usec = USEC_INFINITY },
},
};
}
@@ -528,6 +530,7 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
"%sManagedOOMMemoryPressureLimit: " PERMYRIAD_AS_PERCENT_FORMAT_STR "\n"
"%sManagedOOMPreference: %s\n"
"%sMemoryPressureWatch: %s\n"
"%sCPUPressureWatch: %s\n"
"%sCoredumpReceive: %s\n",
prefix, yes_no(c->io_accounting),
prefix, yes_no(c->memory_accounting),
@@ -563,7 +566,8 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
prefix, managed_oom_mode_to_string(c->moom_mem_pressure),
prefix, PERMYRIAD_AS_PERCENT_FORMAT_VAL(UINT32_SCALE_TO_PERMYRIAD(c->moom_mem_pressure_limit)),
prefix, managed_oom_preference_to_string(c->moom_preference),
prefix, cgroup_pressure_watch_to_string(c->memory_pressure_watch),
prefix, cgroup_pressure_watch_to_string(c->pressure[PRESSURE_MEMORY].watch),
prefix, cgroup_pressure_watch_to_string(c->pressure[PRESSURE_CPU].watch),
prefix, yes_no(c->coredump_receive));
if (c->delegate_subgroup)
@@ -574,9 +578,13 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
fprintf(f, "%sBindNetworkInterface: %s\n",
prefix, c->bind_network_interface);
if (c->memory_pressure_threshold_usec != USEC_INFINITY)
if (c->pressure[PRESSURE_MEMORY].threshold_usec != USEC_INFINITY)
fprintf(f, "%sMemoryPressureThresholdSec: %s\n",
prefix, FORMAT_TIMESPAN(c->memory_pressure_threshold_usec, 1));
prefix, FORMAT_TIMESPAN(c->pressure[PRESSURE_MEMORY].threshold_usec, 1));
if (c->pressure[PRESSURE_CPU].threshold_usec != USEC_INFINITY)
fprintf(f, "%sCPUPressureThresholdSec: %s\n",
prefix, FORMAT_TIMESPAN(c->pressure[PRESSURE_CPU].threshold_usec, 1));
if (c->moom_mem_pressure_duration_usec != USEC_INFINITY)
fprintf(f, "%sManagedOOMMemoryPressureDurationSec: %s\n",
@@ -2107,12 +2115,13 @@ static int unit_update_cgroup(
cgroup_context_apply(u, target_mask, state);
cgroup_xattr_apply(u);
/* For most units we expect that memory monitoring is set up before the unit is started and we won't
* touch it after. For PID 1 this is different though, because we couldn't possibly do that given
* that PID 1 runs before init.scope is even set up. Hence, whenever init.scope is realized, let's
* try to open the memory pressure interface anew. */
/* For most units we expect that pressure monitoring is set up before the unit is started and we
* won't touch it after. For PID 1 this is different though, because we couldn't possibly do that
* given that PID 1 runs before init.scope is even set up. Hence, whenever init.scope is realized,
* let's try to open the pressure interfaces anew. */
if (unit_has_name(u, SPECIAL_INIT_SCOPE))
(void) manager_setup_memory_pressure_event_source(u->manager);
for (PressureResource t = 0; t < _PRESSURE_RESOURCE_MAX; t++)
(void) manager_setup_pressure_event_source(u->manager, t);
return 0;
}
+32 -11
View File
@@ -6,6 +6,7 @@
#include "cpu-set-util.h"
#include "firewall-util.h"
#include "list.h"
#include "psi-util.h"
typedef struct CGroupTasksMax {
/* If scale == 0, just use value; otherwise, value / scale.
@@ -95,14 +96,19 @@ typedef struct CGroupSocketBindItem {
} CGroupSocketBindItem;
typedef enum CGroupPressureWatch {
CGROUP_PRESSURE_WATCH_NO, /* → tells the service payload explicitly not to watch for memory pressure */
CGROUP_PRESSURE_WATCH_NO, /* → tells the service payload explicitly not to watch for pressure */
CGROUP_PRESSURE_WATCH_YES,
CGROUP_PRESSURE_WATCH_AUTO, /* → on if memory account is on anyway for the unit, otherwise off */
CGROUP_PRESSURE_WATCH_SKIP, /* → doesn't set up memory pressure watch, but also doesn't explicitly tell payload to avoid it */
CGROUP_PRESSURE_WATCH_AUTO, /* → on if relevant accounting is on anyway for the unit, otherwise off */
CGROUP_PRESSURE_WATCH_SKIP, /* → doesn't set up pressure watch, but also doesn't explicitly tell payload to avoid it */
_CGROUP_PRESSURE_WATCH_MAX,
_CGROUP_PRESSURE_WATCH_INVALID = -EINVAL,
} CGroupPressureWatch;
typedef struct CGroupPressure {
CGroupPressureWatch watch;
usec_t threshold_usec;
} CGroupPressure;
/* The user-supplied cgroup-related configuration options. This remains mostly immutable while the service
* manager is running (except for an occasional SetProperties() configuration change), outside of reload
* cycles. */
@@ -189,11 +195,8 @@ typedef struct CGroupContext {
usec_t moom_mem_pressure_duration_usec;
ManagedOOMPreference moom_preference;
/* Memory pressure logic */
CGroupPressureWatch memory_pressure_watch;
usec_t memory_pressure_threshold_usec;
/* NB: For now we don't make the period configurable, not the type, nor do we allow multiple
* triggers, nor triggers for non-memory pressure. We might add that later. */
/* Pressure logic */
CGroupPressure pressure[_PRESSURE_RESOURCE_MAX];
NFTSetContext nft_set_context;
@@ -353,11 +356,29 @@ void cgroup_context_free_io_device_latency(CGroupContext *c, CGroupIODeviceLaten
void cgroup_context_remove_bpf_foreign_program(CGroupContext *c, CGroupBPFForeignProgram *p);
void cgroup_context_remove_socket_bind(CGroupSocketBindItem **head);
static inline bool cgroup_context_want_memory_pressure(const CGroupContext *c) {
static inline bool cgroup_context_want_pressure(const CGroupContext *c, PressureResource t) {
assert(c);
assert(t >= 0 && t < _PRESSURE_RESOURCE_MAX);
return c->memory_pressure_watch == CGROUP_PRESSURE_WATCH_YES ||
(c->memory_pressure_watch == CGROUP_PRESSURE_WATCH_AUTO && c->memory_accounting);
if (c->pressure[t].watch == CGROUP_PRESSURE_WATCH_YES)
return true;
if (c->pressure[t].watch != CGROUP_PRESSURE_WATCH_AUTO)
return false;
switch (t) {
case PRESSURE_MEMORY:
return c->memory_accounting;
case PRESSURE_CPU:
return c->cpu_weight != CGROUP_WEIGHT_INVALID ||
c->startup_cpu_weight != CGROUP_WEIGHT_INVALID ||
c->cpu_quota_per_sec_usec != USEC_INFINITY;
default:
assert_not_reached();
}
}
static inline bool cgroup_context_has_device_policy(const CGroupContext *c) {
+15 -9
View File
@@ -427,8 +427,10 @@ const sd_bus_vtable bus_cgroup_vtable[] = {
SD_BUS_PROPERTY("SocketBindDeny", "a(iiqq)", property_get_socket_bind, offsetof(CGroupContext, socket_bind_deny), 0),
SD_BUS_PROPERTY("RestrictNetworkInterfaces", "(bas)", property_get_restrict_network_interfaces, 0, 0),
SD_BUS_PROPERTY("BindNetworkInterface", "s", NULL, offsetof(CGroupContext, bind_network_interface), 0),
SD_BUS_PROPERTY("MemoryPressureWatch", "s", bus_property_get_cgroup_pressure_watch, offsetof(CGroupContext, memory_pressure_watch), 0),
SD_BUS_PROPERTY("MemoryPressureThresholdUSec", "t", bus_property_get_usec, offsetof(CGroupContext, memory_pressure_threshold_usec), 0),
SD_BUS_PROPERTY("MemoryPressureWatch", "s", bus_property_get_cgroup_pressure_watch, offsetof(CGroupContext, pressure[PRESSURE_MEMORY].watch), 0),
SD_BUS_PROPERTY("MemoryPressureThresholdUSec", "t", bus_property_get_usec, offsetof(CGroupContext, pressure[PRESSURE_MEMORY].threshold_usec), 0),
SD_BUS_PROPERTY("CPUPressureWatch", "s", bus_property_get_cgroup_pressure_watch, offsetof(CGroupContext, pressure[PRESSURE_CPU].watch), 0),
SD_BUS_PROPERTY("CPUPressureThresholdUSec", "t", bus_property_get_usec, offsetof(CGroupContext, pressure[PRESSURE_CPU].threshold_usec), 0),
SD_BUS_PROPERTY("NFTSet", "a(iiss)", property_get_cgroup_nft_set, 0, 0),
SD_BUS_PROPERTY("CoredumpReceive", "b", bus_property_get_bool, offsetof(CGroupContext, coredump_receive), 0),
@@ -712,10 +714,12 @@ static int bus_cgroup_set_transient_property(
return 1;
} else if (streq(name, "MemoryPressureWatch")) {
} else if (STR_IN_SET(name, "MemoryPressureWatch", "CPUPressureWatch")) {
CGroupPressureWatch p;
const char *t;
PressureResource pt = streq(name, "MemoryPressureWatch") ? PRESSURE_MEMORY : PRESSURE_CPU;
r = sd_bus_message_read(message, "s", &t);
if (r < 0)
return r;
@@ -729,26 +733,28 @@ static int bus_cgroup_set_transient_property(
}
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->memory_pressure_watch = p;
unit_write_settingf(u, flags, name, "MemoryPressureWatch=%s", strempty(cgroup_pressure_watch_to_string(p)));
c->pressure[pt].watch = p;
unit_write_settingf(u, flags, name, "%s=%s", name, strempty(cgroup_pressure_watch_to_string(p)));
}
return 1;
} else if (streq(name, "MemoryPressureThresholdUSec")) {
} else if (STR_IN_SET(name, "MemoryPressureThresholdUSec", "CPUPressureThresholdUSec")) {
uint64_t t;
PressureResource pt = streq(name, "MemoryPressureThresholdUSec") ? PRESSURE_MEMORY : PRESSURE_CPU;
r = sd_bus_message_read(message, "t", &t);
if (r < 0)
return r;
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->memory_pressure_threshold_usec = t;
c->pressure[pt].threshold_usec = t;
if (t == UINT64_MAX)
unit_write_setting(u, flags, name, "MemoryPressureThresholdUSec=");
unit_write_settingf(u, flags, name, "%s=", name);
else
unit_write_settingf(u, flags, name, "MemoryPressureThresholdUSec=%" PRIu64, t);
unit_write_settingf(u, flags, name, "%s=%" PRIu64, name, t);
}
return 1;
+4 -2
View File
@@ -2980,8 +2980,10 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_PROPERTY("DefaultLimitRTTIME", "t", bus_property_get_rlimit, offsetof(Manager, defaults.rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultLimitRTTIMESoft", "t", bus_property_get_rlimit, offsetof(Manager, defaults.rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultTasksMax", "t", bus_property_get_tasks_max, offsetof(Manager, defaults.tasks_max), 0),
SD_BUS_PROPERTY("DefaultMemoryPressureThresholdUSec", "t", bus_property_get_usec, offsetof(Manager, defaults.memory_pressure_threshold_usec), 0),
SD_BUS_PROPERTY("DefaultMemoryPressureWatch", "s", bus_property_get_cgroup_pressure_watch, offsetof(Manager, defaults.memory_pressure_watch), 0),
SD_BUS_PROPERTY("DefaultMemoryPressureThresholdUSec", "t", bus_property_get_usec, offsetof(Manager, defaults.pressure[PRESSURE_MEMORY].threshold_usec), 0),
SD_BUS_PROPERTY("DefaultMemoryPressureWatch", "s", bus_property_get_cgroup_pressure_watch, offsetof(Manager, defaults.pressure[PRESSURE_MEMORY].watch), 0),
SD_BUS_PROPERTY("DefaultCPUPressureThresholdUSec", "t", bus_property_get_usec, offsetof(Manager, defaults.pressure[PRESSURE_CPU].threshold_usec), 0),
SD_BUS_PROPERTY("DefaultCPUPressureWatch", "s", bus_property_get_cgroup_pressure_watch, offsetof(Manager, defaults.pressure[PRESSURE_CPU].watch), 0),
SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultOOMPolicy", "s", bus_property_get_oom_policy, offsetof(Manager, defaults.oom_policy), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultOOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+83 -45
View File
@@ -2034,7 +2034,7 @@ static int build_environment(
const char *shell,
dev_t journal_stream_dev,
ino_t journal_stream_ino,
const char *memory_pressure_path,
char *const *pressure_path,
bool needs_sandboxing,
char ***ret) {
@@ -2215,25 +2215,38 @@ static int build_environment(
if (r < 0)
return r;
if (memory_pressure_path) {
r = strv_extend_joined_with_size(&e, &n, "MEMORY_PRESSURE_WATCH=", memory_pressure_path);
for (PressureResource t = 0; t < _PRESSURE_RESOURCE_MAX; t++) {
if (!pressure_path[t])
continue;
const PressureResourceInfo *info = pressure_resource_get_info(t);
_cleanup_free_ char *env_watch = strjoin(info->env_watch, "=");
if (!env_watch)
return -ENOMEM;
r = strv_extend_joined_with_size(&e, &n, env_watch, pressure_path[t]);
if (r < 0)
return r;
if (!path_equal(memory_pressure_path, "/dev/null")) {
if (!path_equal(pressure_path[t], "/dev/null")) {
_cleanup_free_ char *b = NULL, *x = NULL;
if (asprintf(&b, "%s " USEC_FMT " " USEC_FMT,
PRESSURE_DEFAULT_TYPE,
cgroup_context->memory_pressure_threshold_usec == USEC_INFINITY ? PRESSURE_DEFAULT_THRESHOLD_USEC :
CLAMP(cgroup_context->memory_pressure_threshold_usec, 1U, PRESSURE_DEFAULT_WINDOW_USEC),
cgroup_context->pressure[t].threshold_usec == USEC_INFINITY ? PRESSURE_DEFAULT_THRESHOLD_USEC :
CLAMP(cgroup_context->pressure[t].threshold_usec, 1U, PRESSURE_DEFAULT_WINDOW_USEC),
PRESSURE_DEFAULT_WINDOW_USEC) < 0)
return -ENOMEM;
if (base64mem(b, strlen(b) + 1, &x) < 0)
return -ENOMEM;
r = strv_extend_joined_with_size(&e, &n, "MEMORY_PRESSURE_WRITE=", x);
_cleanup_free_ char *env_write = strjoin(info->env_write, "=");
if (!env_write)
return -ENOMEM;
r = strv_extend_joined_with_size(&e, &n, env_write, x);
if (r < 0)
return r;
}
@@ -3855,7 +3868,7 @@ static int apply_mount_namespace(
const ExecParameters *params,
const ExecRuntime *runtime,
const PinnedResource *rootfs,
const char *memory_pressure_path,
char *const *pressure_path,
bool needs_sandboxing,
uid_t exec_directory_uid,
gid_t exec_directory_gid,
@@ -3887,16 +3900,28 @@ static int apply_mount_namespace(
if (r < 0)
return r;
/* We need to make the pressure path writable even if /sys/fs/cgroups is made read-only, as the
* service will need to write to it in order to start the notifications. */
if (exec_is_cgroup_mount_read_only(context) && memory_pressure_path && !streq(memory_pressure_path, "/dev/null")) {
/* We need to make the pressure paths writable even if /sys/fs/cgroups is made read-only, as the
* service will need to write to them in order to start the notifications. */
bool need_pressure_rw = false;
for (PressureResource t = 0; t < _PRESSURE_RESOURCE_MAX; t++)
if (pressure_path[t] && !streq(pressure_path[t], "/dev/null")) {
need_pressure_rw = true;
break;
}
if (exec_is_cgroup_mount_read_only(context) && need_pressure_rw) {
read_write_paths_cleanup = strv_copy(context->read_write_paths);
if (!read_write_paths_cleanup)
return -ENOMEM;
r = strv_extend(&read_write_paths_cleanup, memory_pressure_path);
if (r < 0)
return r;
for (PressureResource t = 0; t < _PRESSURE_RESOURCE_MAX; t++) {
if (!pressure_path[t] || streq(pressure_path[t], "/dev/null"))
continue;
r = strv_extend(&read_write_paths_cleanup, pressure_path[t]);
if (r < 0)
return r;
}
read_write_paths = read_write_paths_cleanup;
} else
@@ -4689,7 +4714,7 @@ static int setup_delegated_namespaces(
const ExecRuntime *runtime,
const PinnedResource *rootfs,
bool delegate,
const char *memory_pressure_path,
char *const *pressure_path,
uid_t uid,
gid_t gid,
const ExecCommand *command,
@@ -4820,7 +4845,7 @@ static int setup_delegated_namespaces(
params,
runtime,
rootfs,
memory_pressure_path,
pressure_path,
needs_sandboxing,
uid,
gid,
@@ -5146,6 +5171,10 @@ static int setup_term_environment(const ExecContext *context, char ***env) {
return strv_env_replace_strdup(env, "TERM=" FALLBACK_TERM);
}
static inline void free_pressure_paths(char *(*p)[_PRESSURE_RESOURCE_MAX]) {
free_many_charp(*p, _PRESSURE_RESOURCE_MAX);
}
int exec_invoke(
const ExecCommand *command,
const ExecContext *context,
@@ -5157,7 +5186,8 @@ int exec_invoke(
_cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **joined_exec_search_path = NULL, **accum_env = NULL;
int r;
const char *username = NULL, *groupname = NULL;
_cleanup_free_ char *home_buffer = NULL, *memory_pressure_path = NULL, *own_user = NULL;
_cleanup_free_ char *home_buffer = NULL, *own_user = NULL;
_cleanup_(free_pressure_paths) char *pressure_path[_PRESSURE_RESOURCE_MAX] = {};
const char *pwent_home = NULL, *shell = NULL;
dev_t journal_stream_dev = 0;
ino_t journal_stream_ino = 0;
@@ -5753,36 +5783,44 @@ int exec_invoke(
}
if (is_pressure_supported() > 0) {
if (cgroup_context_want_memory_pressure(cgroup_context)) {
r = cg_get_path(params->cgroup_path, "memory.pressure", &memory_pressure_path);
if (r < 0) {
*exit_status = EXIT_MEMORY;
return log_oom();
}
for (PressureResource t = 0; t < _PRESSURE_RESOURCE_MAX; t++) {
if (cgroup_context_want_pressure(cgroup_context, t)) {
_cleanup_free_ char *pressure_file = strjoin(pressure_resource_to_string(t), ".pressure");
if (!pressure_file) {
*exit_status = EXIT_MEMORY;
return log_oom();
}
r = chmod_and_chown(memory_pressure_path, 0644, uid, gid);
if (r < 0) {
log_full_errno(r == -ENOENT || ERRNO_IS_PRIVILEGE(r) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to adjust ownership of '%s', ignoring: %m", memory_pressure_path);
memory_pressure_path = mfree(memory_pressure_path);
}
/* First we use the current cgroup path to chmod and chown the memory pressure path, then pass the path relative
* to the cgroup namespace to environment variables and mounts. If chown/chmod fails, we should not pass memory
* pressure path environment variable or read-write mount to the unit. This is why we check if
* memory_pressure_path != NULL in the conditional below. */
if (memory_pressure_path && needs_sandboxing && exec_needs_cgroup_namespace(context)) {
memory_pressure_path = mfree(memory_pressure_path);
r = cg_get_path("/", "memory.pressure", &memory_pressure_path);
r = cg_get_path(params->cgroup_path, pressure_file, &pressure_path[t]);
if (r < 0) {
*exit_status = EXIT_MEMORY;
return log_oom();
}
}
} else if (cgroup_context->memory_pressure_watch == CGROUP_PRESSURE_WATCH_NO) {
memory_pressure_path = strdup("/dev/null"); /* /dev/null is explicit indicator for turning of memory pressure watch */
if (!memory_pressure_path) {
*exit_status = EXIT_MEMORY;
return log_oom();
r = chmod_and_chown(pressure_path[t], 0644, uid, gid);
if (r < 0) {
log_full_errno(r == -ENOENT || ERRNO_IS_PRIVILEGE(r) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to adjust ownership of '%s', ignoring: %m", pressure_path[t]);
pressure_path[t] = mfree(pressure_path[t]);
}
/* First we use the current cgroup path to chmod and chown the pressure path, then pass the
* path relative to the cgroup namespace to environment variables and mounts. If chown/chmod
* fails, we should not pass pressure path environment variable or read-write mount to the
* unit. This is why we check if pressure_path[t] != NULL in the conditional below. */
if (pressure_path[t] && needs_sandboxing && exec_needs_cgroup_namespace(context)) {
pressure_path[t] = mfree(pressure_path[t]);
r = cg_get_path("/", pressure_file, &pressure_path[t]);
if (r < 0) {
*exit_status = EXIT_MEMORY;
return log_oom();
}
}
} else if (cgroup_context->pressure[t].watch == CGROUP_PRESSURE_WATCH_NO) {
pressure_path[t] = strdup("/dev/null"); /* /dev/null is explicit indicator for turning off pressure watch */
if (!pressure_path[t]) {
*exit_status = EXIT_MEMORY;
return log_oom();
}
}
}
}
@@ -5829,7 +5867,7 @@ int exec_invoke(
shell,
journal_stream_dev,
journal_stream_ino,
memory_pressure_path,
pressure_path,
needs_sandboxing,
&our_env);
if (r < 0) {
@@ -6047,7 +6085,7 @@ int exec_invoke(
runtime,
&rootfs,
/* delegate= */ false,
memory_pressure_path,
pressure_path,
uid,
gid,
command,
@@ -6144,7 +6182,7 @@ int exec_invoke(
runtime,
&rootfs,
/* delegate= */ true,
memory_pressure_path,
pressure_path,
uid,
gid,
command,
+24 -6
View File
@@ -279,7 +279,11 @@ static int exec_cgroup_context_serialize(const CGroupContext *c, FILE *f) {
if (r < 0)
return r;
r = serialize_item(f, "exec-cgroup-context-memory-pressure-watch", cgroup_pressure_watch_to_string(c->memory_pressure_watch));
r = serialize_item(f, "exec-cgroup-context-memory-pressure-watch", cgroup_pressure_watch_to_string(c->pressure[PRESSURE_MEMORY].watch));
if (r < 0)
return r;
r = serialize_item(f, "exec-cgroup-context-cpu-pressure-watch", cgroup_pressure_watch_to_string(c->pressure[PRESSURE_CPU].watch));
if (r < 0)
return r;
@@ -287,8 +291,14 @@ static int exec_cgroup_context_serialize(const CGroupContext *c, FILE *f) {
if (r < 0)
return r;
if (c->memory_pressure_threshold_usec != USEC_INFINITY) {
r = serialize_usec(f, "exec-cgroup-context-memory-pressure-threshold-usec", c->memory_pressure_threshold_usec);
if (c->pressure[PRESSURE_MEMORY].threshold_usec != USEC_INFINITY) {
r = serialize_usec(f, "exec-cgroup-context-memory-pressure-threshold-usec", c->pressure[PRESSURE_MEMORY].threshold_usec);
if (r < 0)
return r;
}
if (c->pressure[PRESSURE_CPU].threshold_usec != USEC_INFINITY) {
r = serialize_usec(f, "exec-cgroup-context-cpu-pressure-threshold-usec", c->pressure[PRESSURE_CPU].threshold_usec);
if (r < 0)
return r;
}
@@ -621,15 +631,23 @@ static int exec_cgroup_context_deserialize(CGroupContext *c, FILE *f) {
if (r < 0)
return r;
} else if ((val = startswith(l, "exec-cgroup-context-memory-pressure-watch="))) {
c->memory_pressure_watch = cgroup_pressure_watch_from_string(val);
if (c->memory_pressure_watch < 0)
c->pressure[PRESSURE_MEMORY].watch = cgroup_pressure_watch_from_string(val);
if (c->pressure[PRESSURE_MEMORY].watch < 0)
return -EINVAL;
} else if ((val = startswith(l, "exec-cgroup-context-cpu-pressure-watch="))) {
c->pressure[PRESSURE_CPU].watch = cgroup_pressure_watch_from_string(val);
if (c->pressure[PRESSURE_CPU].watch < 0)
return -EINVAL;
} else if ((val = startswith(l, "exec-cgroup-context-delegate-subgroup="))) {
r = free_and_strdup(&c->delegate_subgroup, val);
if (r < 0)
return r;
} else if ((val = startswith(l, "exec-cgroup-context-memory-pressure-threshold-usec="))) {
r = deserialize_usec(val, &c->memory_pressure_threshold_usec);
r = deserialize_usec(val, &c->pressure[PRESSURE_MEMORY].threshold_usec);
if (r < 0)
return r;
} else if ((val = startswith(l, "exec-cgroup-context-cpu-pressure-threshold-usec="))) {
r = deserialize_usec(val, &c->pressure[PRESSURE_CPU].threshold_usec);
if (r < 0)
return r;
} else if ((val = startswith(l, "exec-cgroup-context-device-allow="))) {
+4 -2
View File
@@ -276,8 +276,10 @@
{{type}}.SocketBindAllow, config_parse_cgroup_socket_bind, 0, offsetof({{type}}, cgroup_context.socket_bind_allow)
{{type}}.SocketBindDeny, config_parse_cgroup_socket_bind, 0, offsetof({{type}}, cgroup_context.socket_bind_deny)
{{type}}.RestrictNetworkInterfaces, config_parse_restrict_network_interfaces, 0, offsetof({{type}}, cgroup_context)
{{type}}.MemoryPressureThresholdSec, config_parse_sec, 0, offsetof({{type}}, cgroup_context.memory_pressure_threshold_usec)
{{type}}.MemoryPressureWatch, config_parse_memory_pressure_watch, 0, offsetof({{type}}, cgroup_context.memory_pressure_watch)
{{type}}.MemoryPressureThresholdSec, config_parse_sec, 0, offsetof({{type}}, cgroup_context.pressure[PRESSURE_MEMORY].threshold_usec)
{{type}}.MemoryPressureWatch, config_parse_pressure_watch, 0, offsetof({{type}}, cgroup_context.pressure[PRESSURE_MEMORY].watch)
{{type}}.CPUPressureThresholdSec, config_parse_sec, 0, offsetof({{type}}, cgroup_context.pressure[PRESSURE_CPU].threshold_usec)
{{type}}.CPUPressureWatch, config_parse_pressure_watch, 0, offsetof({{type}}, cgroup_context.pressure[PRESSURE_CPU].watch)
{{type}}.NFTSet, config_parse_cgroup_nft_set, NFT_SET_PARSE_CGROUP, offsetof({{type}}, cgroup_context)
{{type}}.CoredumpReceive, config_parse_bool, 0, offsetof({{type}}, cgroup_context.coredump_receive)
{{type}}.BindNetworkInterface, config_parse_bind_network_interface, 0, offsetof({{type}}, cgroup_context)
+1 -1
View File
@@ -154,7 +154,7 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_service_timeout_failure_mode, service_time
DEFINE_CONFIG_PARSE_ENUM(config_parse_socket_bind, socket_address_bind_ipv6_only_or_bool, SocketAddressBindIPv6Only);
DEFINE_CONFIG_PARSE_ENUM(config_parse_oom_policy, oom_policy, OOMPolicy);
DEFINE_CONFIG_PARSE_ENUM(config_parse_managed_oom_preference, managed_oom_preference, ManagedOOMPreference);
DEFINE_CONFIG_PARSE_ENUM(config_parse_memory_pressure_watch, cgroup_pressure_watch, CGroupPressureWatch);
DEFINE_CONFIG_PARSE_ENUM(config_parse_pressure_watch, cgroup_pressure_watch, CGroupPressureWatch);
DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_ip_tos, ip_tos, int, -1);
DEFINE_CONFIG_PARSE_PTR(config_parse_cg_weight, cg_weight_parse, uint64_t);
DEFINE_CONFIG_PARSE_PTR(config_parse_cg_cpu_weight, cg_cpu_weight_parse, uint64_t);
+1 -1
View File
@@ -164,7 +164,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_watchdog_sec);
CONFIG_PARSER_PROTOTYPE(config_parse_tty_size);
CONFIG_PARSER_PROTOTYPE(config_parse_log_filter_patterns);
CONFIG_PARSER_PROTOTYPE(config_parse_open_file);
CONFIG_PARSER_PROTOTYPE(config_parse_memory_pressure_watch);
CONFIG_PARSER_PROTOTYPE(config_parse_pressure_watch);
CONFIG_PARSER_PROTOTYPE(config_parse_cgroup_nft_set);
CONFIG_PARSER_PROTOTYPE(config_parse_mount_node);
CONFIG_PARSER_PROTOTYPE(config_parse_concurrency_max);
+80 -78
View File
@@ -747,89 +747,91 @@ static int config_parse_crash_reboot(
static int parse_config_file(void) {
const ConfigTableItem items[] = {
{ "Manager", "LogLevel", config_parse_level2, 0, NULL },
{ "Manager", "LogTarget", config_parse_target, 0, NULL },
{ "Manager", "LogColor", config_parse_color, 0, NULL },
{ "Manager", "LogLocation", config_parse_location, 0, NULL },
{ "Manager", "LogTime", config_parse_time, 0, NULL },
{ "Manager", "DumpCore", config_parse_bool, 0, &arg_dump_core },
{ "Manager", "CrashChVT", /* legacy */ config_parse_crash_chvt, 0, &arg_crash_chvt },
{ "Manager", "CrashChangeVT", config_parse_crash_chvt, 0, &arg_crash_chvt },
{ "Manager", "CrashShell", config_parse_bool, 0, &arg_crash_shell },
{ "Manager", "CrashReboot", config_parse_crash_reboot, 0, &arg_crash_action },
{ "Manager", "CrashAction", config_parse_crash_action, 0, &arg_crash_action },
{ "Manager", "ShowStatus", config_parse_show_status, 0, &arg_show_status },
{ "Manager", "StatusUnitFormat", config_parse_status_unit_format, 0, &arg_status_unit_format },
{ "Manager", "CPUAffinity", config_parse_cpu_set, 0, &arg_cpu_affinity },
{ "Manager", "NUMAPolicy", config_parse_numa_policy, 0, &arg_numa_policy.type },
{ "Manager", "NUMAMask", config_parse_numa_mask, 0, &arg_numa_policy.nodes },
{ "Manager", "JoinControllers", config_parse_warn_compat, DISABLED_LEGACY, NULL },
{ "Manager", "RuntimeWatchdogSec", config_parse_watchdog_sec, 0, &arg_runtime_watchdog },
{ "Manager", "RuntimeWatchdogPreSec", config_parse_watchdog_sec, 0, &arg_pretimeout_watchdog },
{ "Manager", "RebootWatchdogSec", config_parse_watchdog_sec, 0, &arg_reboot_watchdog },
{ "Manager", "ShutdownWatchdogSec", config_parse_watchdog_sec, 0, &arg_reboot_watchdog }, /* obsolete alias */
{ "Manager", "KExecWatchdogSec", config_parse_watchdog_sec, 0, &arg_kexec_watchdog },
{ "Manager", "WatchdogDevice", config_parse_path, 0, &arg_watchdog_device },
{ "Manager", "RuntimeWatchdogPreGovernor", config_parse_string, CONFIG_PARSE_STRING_SAFE, &arg_watchdog_pretimeout_governor },
{ "Manager", "CapabilityBoundingSet", config_parse_capability_set, 0, &arg_capability_bounding_set },
{ "Manager", "NoNewPrivileges", config_parse_bool, 0, &arg_no_new_privs },
{ "Manager", "ProtectSystem", config_parse_protect_system_pid1, 0, &arg_protect_system },
{ "Manager", "LogLevel", config_parse_level2, 0, NULL },
{ "Manager", "LogTarget", config_parse_target, 0, NULL },
{ "Manager", "LogColor", config_parse_color, 0, NULL },
{ "Manager", "LogLocation", config_parse_location, 0, NULL },
{ "Manager", "LogTime", config_parse_time, 0, NULL },
{ "Manager", "DumpCore", config_parse_bool, 0, &arg_dump_core },
{ "Manager", "CrashChVT", /* legacy */ config_parse_crash_chvt, 0, &arg_crash_chvt },
{ "Manager", "CrashChangeVT", config_parse_crash_chvt, 0, &arg_crash_chvt },
{ "Manager", "CrashShell", config_parse_bool, 0, &arg_crash_shell },
{ "Manager", "CrashReboot", config_parse_crash_reboot, 0, &arg_crash_action },
{ "Manager", "CrashAction", config_parse_crash_action, 0, &arg_crash_action },
{ "Manager", "ShowStatus", config_parse_show_status, 0, &arg_show_status },
{ "Manager", "StatusUnitFormat", config_parse_status_unit_format, 0, &arg_status_unit_format },
{ "Manager", "CPUAffinity", config_parse_cpu_set, 0, &arg_cpu_affinity },
{ "Manager", "NUMAPolicy", config_parse_numa_policy, 0, &arg_numa_policy.type },
{ "Manager", "NUMAMask", config_parse_numa_mask, 0, &arg_numa_policy.nodes },
{ "Manager", "JoinControllers", config_parse_warn_compat, DISABLED_LEGACY, NULL },
{ "Manager", "RuntimeWatchdogSec", config_parse_watchdog_sec, 0, &arg_runtime_watchdog },
{ "Manager", "RuntimeWatchdogPreSec", config_parse_watchdog_sec, 0, &arg_pretimeout_watchdog },
{ "Manager", "RebootWatchdogSec", config_parse_watchdog_sec, 0, &arg_reboot_watchdog },
{ "Manager", "ShutdownWatchdogSec", config_parse_watchdog_sec, 0, &arg_reboot_watchdog }, /* obsolete alias */
{ "Manager", "KExecWatchdogSec", config_parse_watchdog_sec, 0, &arg_kexec_watchdog },
{ "Manager", "WatchdogDevice", config_parse_path, 0, &arg_watchdog_device },
{ "Manager", "RuntimeWatchdogPreGovernor", config_parse_string, CONFIG_PARSE_STRING_SAFE, &arg_watchdog_pretimeout_governor },
{ "Manager", "CapabilityBoundingSet", config_parse_capability_set, 0, &arg_capability_bounding_set },
{ "Manager", "NoNewPrivileges", config_parse_bool, 0, &arg_no_new_privs },
{ "Manager", "ProtectSystem", config_parse_protect_system_pid1, 0, &arg_protect_system },
#if HAVE_SECCOMP
{ "Manager", "SystemCallArchitectures", config_parse_syscall_archs, 0, &arg_syscall_archs },
{ "Manager", "SystemCallArchitectures", config_parse_syscall_archs, 0, &arg_syscall_archs },
#else
{ "Manager", "SystemCallArchitectures", config_parse_warn_compat, DISABLED_CONFIGURATION, NULL },
{ "Manager", "SystemCallArchitectures", config_parse_warn_compat, DISABLED_CONFIGURATION, NULL },
#endif
{ "Manager", "TimerSlackNSec", config_parse_nsec, 0, &arg_timer_slack_nsec },
{ "Manager", "DefaultTimerAccuracySec", config_parse_sec, 0, &arg_defaults.timer_accuracy_usec },
{ "Manager", "DefaultStandardOutput", config_parse_output_restricted, 0, &arg_defaults.std_output },
{ "Manager", "DefaultStandardError", config_parse_output_restricted, 0, &arg_defaults.std_error },
{ "Manager", "DefaultTimeoutStartSec", config_parse_sec, 0, &arg_defaults.timeout_start_usec },
{ "Manager", "DefaultTimeoutStopSec", config_parse_sec, 0, &arg_defaults.timeout_stop_usec },
{ "Manager", "DefaultTimeoutAbortSec", config_parse_default_timeout_abort, 0, NULL },
{ "Manager", "DefaultDeviceTimeoutSec", config_parse_sec, 0, &arg_defaults.device_timeout_usec },
{ "Manager", "DefaultRestartSec", config_parse_sec, 0, &arg_defaults.restart_usec },
{ "Manager", "DefaultStartLimitInterval", config_parse_sec, 0, &arg_defaults.start_limit.interval }, /* obsolete alias */
{ "Manager", "DefaultStartLimitIntervalSec", config_parse_sec, 0, &arg_defaults.start_limit.interval },
{ "Manager", "DefaultStartLimitBurst", config_parse_unsigned, 0, &arg_defaults.start_limit.burst },
{ "Manager", "DefaultRestrictSUIDSGID", config_parse_bool, 0, &arg_defaults.restrict_suid_sgid },
{ "Manager", "DefaultEnvironment", config_parse_environ, arg_runtime_scope, &arg_default_environment },
{ "Manager", "ManagerEnvironment", config_parse_environ, arg_runtime_scope, &arg_manager_environment },
{ "Manager", "DefaultLimitCPU", config_parse_rlimit, RLIMIT_CPU, arg_defaults.rlimit },
{ "Manager", "DefaultLimitFSIZE", config_parse_rlimit, RLIMIT_FSIZE, arg_defaults.rlimit },
{ "Manager", "DefaultLimitDATA", config_parse_rlimit, RLIMIT_DATA, arg_defaults.rlimit },
{ "Manager", "DefaultLimitSTACK", config_parse_rlimit, RLIMIT_STACK, arg_defaults.rlimit },
{ "Manager", "DefaultLimitCORE", config_parse_rlimit, RLIMIT_CORE, arg_defaults.rlimit },
{ "Manager", "DefaultLimitRSS", config_parse_rlimit, RLIMIT_RSS, arg_defaults.rlimit },
{ "Manager", "DefaultLimitNOFILE", config_parse_rlimit, RLIMIT_NOFILE, arg_defaults.rlimit },
{ "Manager", "DefaultLimitAS", config_parse_rlimit, RLIMIT_AS, arg_defaults.rlimit },
{ "Manager", "DefaultLimitNPROC", config_parse_rlimit, RLIMIT_NPROC, arg_defaults.rlimit },
{ "Manager", "DefaultLimitMEMLOCK", config_parse_rlimit, RLIMIT_MEMLOCK, arg_defaults.rlimit },
{ "Manager", "DefaultLimitLOCKS", config_parse_rlimit, RLIMIT_LOCKS, arg_defaults.rlimit },
{ "Manager", "DefaultLimitSIGPENDING", config_parse_rlimit, RLIMIT_SIGPENDING, arg_defaults.rlimit },
{ "Manager", "DefaultLimitMSGQUEUE", config_parse_rlimit, RLIMIT_MSGQUEUE, arg_defaults.rlimit },
{ "Manager", "DefaultLimitNICE", config_parse_rlimit, RLIMIT_NICE, arg_defaults.rlimit },
{ "Manager", "DefaultLimitRTPRIO", config_parse_rlimit, RLIMIT_RTPRIO, arg_defaults.rlimit },
{ "Manager", "DefaultLimitRTTIME", config_parse_rlimit, RLIMIT_RTTIME, arg_defaults.rlimit },
{ "Manager", "DefaultCPUAccounting", config_parse_warn_compat, DISABLED_LEGACY, NULL },
{ "Manager", "DefaultIOAccounting", config_parse_bool, 0, &arg_defaults.io_accounting },
{ "Manager", "DefaultIPAccounting", config_parse_bool, 0, &arg_defaults.ip_accounting },
{ "Manager", "DefaultBlockIOAccounting", config_parse_warn_compat, DISABLED_LEGACY, NULL },
{ "Manager", "DefaultMemoryAccounting", config_parse_bool, 0, &arg_defaults.memory_accounting },
{ "Manager", "DefaultTasksAccounting", config_parse_bool, 0, &arg_defaults.tasks_accounting },
{ "Manager", "DefaultTasksMax", config_parse_tasks_max, 0, &arg_defaults.tasks_max },
{ "Manager", "DefaultMemoryPressureThresholdSec", config_parse_sec, 0, &arg_defaults.memory_pressure_threshold_usec },
{ "Manager", "DefaultMemoryPressureWatch", config_parse_memory_pressure_watch, 0, &arg_defaults.memory_pressure_watch },
{ "Manager", "CtrlAltDelBurstAction", config_parse_emergency_action, arg_runtime_scope, &arg_cad_burst_action },
{ "Manager", "DefaultOOMPolicy", config_parse_oom_policy, 0, &arg_defaults.oom_policy },
{ "Manager", "DefaultOOMScoreAdjust", config_parse_oom_score_adjust, 0, NULL },
{ "Manager", "ReloadLimitIntervalSec", config_parse_sec, 0, &arg_reload_limit_interval_sec },
{ "Manager", "ReloadLimitBurst", config_parse_unsigned, 0, &arg_reload_limit_burst },
{ "Manager", "DefaultMemoryZSwapWriteback", config_parse_bool, 0, &arg_defaults.memory_zswap_writeback },
{ "Manager", "MinimumUptimeSec", config_parse_sec, 0, &arg_minimum_uptime_usec },
{ "Manager", "TimerSlackNSec", config_parse_nsec, 0, &arg_timer_slack_nsec },
{ "Manager", "DefaultTimerAccuracySec", config_parse_sec, 0, &arg_defaults.timer_accuracy_usec },
{ "Manager", "DefaultStandardOutput", config_parse_output_restricted, 0, &arg_defaults.std_output },
{ "Manager", "DefaultStandardError", config_parse_output_restricted, 0, &arg_defaults.std_error },
{ "Manager", "DefaultTimeoutStartSec", config_parse_sec, 0, &arg_defaults.timeout_start_usec },
{ "Manager", "DefaultTimeoutStopSec", config_parse_sec, 0, &arg_defaults.timeout_stop_usec },
{ "Manager", "DefaultTimeoutAbortSec", config_parse_default_timeout_abort, 0, NULL },
{ "Manager", "DefaultDeviceTimeoutSec", config_parse_sec, 0, &arg_defaults.device_timeout_usec },
{ "Manager", "DefaultRestartSec", config_parse_sec, 0, &arg_defaults.restart_usec },
{ "Manager", "DefaultStartLimitInterval", config_parse_sec, 0, &arg_defaults.start_limit.interval }, /* obsolete alias */
{ "Manager", "DefaultStartLimitIntervalSec", config_parse_sec, 0, &arg_defaults.start_limit.interval },
{ "Manager", "DefaultStartLimitBurst", config_parse_unsigned, 0, &arg_defaults.start_limit.burst },
{ "Manager", "DefaultRestrictSUIDSGID", config_parse_bool, 0, &arg_defaults.restrict_suid_sgid },
{ "Manager", "DefaultEnvironment", config_parse_environ, arg_runtime_scope, &arg_default_environment },
{ "Manager", "ManagerEnvironment", config_parse_environ, arg_runtime_scope, &arg_manager_environment },
{ "Manager", "DefaultLimitCPU", config_parse_rlimit, RLIMIT_CPU, arg_defaults.rlimit },
{ "Manager", "DefaultLimitFSIZE", config_parse_rlimit, RLIMIT_FSIZE, arg_defaults.rlimit },
{ "Manager", "DefaultLimitDATA", config_parse_rlimit, RLIMIT_DATA, arg_defaults.rlimit },
{ "Manager", "DefaultLimitSTACK", config_parse_rlimit, RLIMIT_STACK, arg_defaults.rlimit },
{ "Manager", "DefaultLimitCORE", config_parse_rlimit, RLIMIT_CORE, arg_defaults.rlimit },
{ "Manager", "DefaultLimitRSS", config_parse_rlimit, RLIMIT_RSS, arg_defaults.rlimit },
{ "Manager", "DefaultLimitNOFILE", config_parse_rlimit, RLIMIT_NOFILE, arg_defaults.rlimit },
{ "Manager", "DefaultLimitAS", config_parse_rlimit, RLIMIT_AS, arg_defaults.rlimit },
{ "Manager", "DefaultLimitNPROC", config_parse_rlimit, RLIMIT_NPROC, arg_defaults.rlimit },
{ "Manager", "DefaultLimitMEMLOCK", config_parse_rlimit, RLIMIT_MEMLOCK, arg_defaults.rlimit },
{ "Manager", "DefaultLimitLOCKS", config_parse_rlimit, RLIMIT_LOCKS, arg_defaults.rlimit },
{ "Manager", "DefaultLimitSIGPENDING", config_parse_rlimit, RLIMIT_SIGPENDING, arg_defaults.rlimit },
{ "Manager", "DefaultLimitMSGQUEUE", config_parse_rlimit, RLIMIT_MSGQUEUE, arg_defaults.rlimit },
{ "Manager", "DefaultLimitNICE", config_parse_rlimit, RLIMIT_NICE, arg_defaults.rlimit },
{ "Manager", "DefaultLimitRTPRIO", config_parse_rlimit, RLIMIT_RTPRIO, arg_defaults.rlimit },
{ "Manager", "DefaultLimitRTTIME", config_parse_rlimit, RLIMIT_RTTIME, arg_defaults.rlimit },
{ "Manager", "DefaultCPUAccounting", config_parse_warn_compat, DISABLED_LEGACY, NULL },
{ "Manager", "DefaultIOAccounting", config_parse_bool, 0, &arg_defaults.io_accounting },
{ "Manager", "DefaultIPAccounting", config_parse_bool, 0, &arg_defaults.ip_accounting },
{ "Manager", "DefaultBlockIOAccounting", config_parse_warn_compat, DISABLED_LEGACY, NULL },
{ "Manager", "DefaultMemoryAccounting", config_parse_bool, 0, &arg_defaults.memory_accounting },
{ "Manager", "DefaultTasksAccounting", config_parse_bool, 0, &arg_defaults.tasks_accounting },
{ "Manager", "DefaultTasksMax", config_parse_tasks_max, 0, &arg_defaults.tasks_max },
{ "Manager", "DefaultMemoryPressureThresholdSec", config_parse_sec, 0, &arg_defaults.pressure[PRESSURE_MEMORY].threshold_usec },
{ "Manager", "DefaultMemoryPressureWatch", config_parse_pressure_watch, 0, &arg_defaults.pressure[PRESSURE_MEMORY].watch },
{ "Manager", "DefaultCPUPressureThresholdSec", config_parse_sec, 0, &arg_defaults.pressure[PRESSURE_CPU].threshold_usec },
{ "Manager", "DefaultCPUPressureWatch", config_parse_pressure_watch, 0, &arg_defaults.pressure[PRESSURE_CPU].watch },
{ "Manager", "CtrlAltDelBurstAction", config_parse_emergency_action, arg_runtime_scope, &arg_cad_burst_action },
{ "Manager", "DefaultOOMPolicy", config_parse_oom_policy, 0, &arg_defaults.oom_policy },
{ "Manager", "DefaultOOMScoreAdjust", config_parse_oom_score_adjust, 0, NULL },
{ "Manager", "ReloadLimitIntervalSec", config_parse_sec, 0, &arg_reload_limit_interval_sec },
{ "Manager", "ReloadLimitBurst", config_parse_unsigned, 0, &arg_reload_limit_burst },
{ "Manager", "DefaultMemoryZSwapWriteback", config_parse_bool, 0, &arg_defaults.memory_zswap_writeback },
{ "Manager", "MinimumUptimeSec", config_parse_sec, 0, &arg_minimum_uptime_usec },
#if ENABLE_SMACK
{ "Manager", "DefaultSmackProcessLabel", config_parse_string, 0, &arg_defaults.smack_process_label },
{ "Manager", "DefaultSmackProcessLabel", config_parse_string, 0, &arg_defaults.smack_process_label },
#else
{ "Manager", "DefaultSmackProcessLabel", config_parse_warn_compat, DISABLED_CONFIGURATION, NULL },
{ "Manager", "DefaultSmackProcessLabel", config_parse_warn_compat, DISABLED_CONFIGURATION, NULL },
#endif
{}
};
+36 -19
View File
@@ -616,6 +616,8 @@ static char** sanitize_environment(char **l) {
l,
"CACHE_DIRECTORY",
"CONFIGURATION_DIRECTORY",
"CPU_PRESSURE_WATCH",
"CPU_PRESSURE_WRITE",
"CREDENTIALS_DIRECTORY",
"EXIT_CODE",
"EXIT_STATUS",
@@ -796,26 +798,37 @@ static int manager_setup_sigchld_event_source(Manager *m) {
return 0;
}
int manager_setup_memory_pressure_event_source(Manager *m) {
typedef int (*pressure_add_t)(sd_event *, sd_event_source **, sd_event_handler_t, void *);
typedef int (*pressure_set_period_t)(sd_event_source *, usec_t, usec_t);
static const struct {
pressure_add_t add;
pressure_set_period_t set_period;
} pressure_dispatch_table[_PRESSURE_RESOURCE_MAX] = {
[PRESSURE_MEMORY] = { sd_event_add_memory_pressure, sd_event_source_set_memory_pressure_period },
[PRESSURE_CPU] = { sd_event_add_cpu_pressure, sd_event_source_set_cpu_pressure_period },
};
int manager_setup_pressure_event_source(Manager *m, PressureResource t) {
int r;
assert(m);
assert(t >= 0 && t < _PRESSURE_RESOURCE_MAX);
m->memory_pressure_event_source = sd_event_source_disable_unref(m->memory_pressure_event_source);
m->pressure_event_source[t] = sd_event_source_disable_unref(m->pressure_event_source[t]);
r = sd_event_add_memory_pressure(m->event, &m->memory_pressure_event_source, NULL, NULL);
r = pressure_dispatch_table[t].add(m->event, &m->pressure_event_source[t], NULL, NULL);
if (r < 0)
log_full_errno(ERRNO_IS_NOT_SUPPORTED(r) || ERRNO_IS_PRIVILEGE(r) || (r == -EHOSTDOWN) ? LOG_DEBUG : LOG_NOTICE, r,
"Failed to establish memory pressure event source, ignoring: %m");
else if (m->defaults.memory_pressure_threshold_usec != USEC_INFINITY) {
"Failed to establish %s pressure event source, ignoring: %m", pressure_resource_to_string(t));
else if (m->defaults.pressure[t].threshold_usec != USEC_INFINITY) {
/* If there's a default memory pressure threshold set, also apply it to the service manager itself */
r = sd_event_source_set_memory_pressure_period(
m->memory_pressure_event_source,
m->defaults.memory_pressure_threshold_usec,
MEMORY_PRESSURE_DEFAULT_WINDOW_USEC);
r = pressure_dispatch_table[t].set_period(
m->pressure_event_source[t],
m->defaults.pressure[t].threshold_usec,
PRESSURE_DEFAULT_WINDOW_USEC);
if (r < 0)
log_warning_errno(r, "Failed to adjust memory pressure threshold, ignoring: %m");
log_warning_errno(r, "Failed to adjust %s pressure threshold, ignoring: %m", pressure_resource_to_string(t));
}
return 0;
@@ -1001,9 +1014,11 @@ int manager_new(RuntimeScope runtime_scope, ManagerTestRunFlags test_run_flags,
if (r < 0)
return r;
r = manager_setup_memory_pressure_event_source(m);
if (r < 0)
return r;
for (PressureResource t = 0; t < _PRESSURE_RESOURCE_MAX; t++) {
r = manager_setup_pressure_event_source(m, t);
if (r < 0)
return r;
}
#if HAVE_LIBBPF
if (MANAGER_IS_SYSTEM(m) && bpf_restrict_fs_supported(/* initialize= */ true)) {
@@ -1711,7 +1726,8 @@ Manager* manager_free(Manager *m) {
sd_event_source_unref(m->user_lookup_event_source);
sd_event_source_unref(m->handoff_timestamp_event_source);
sd_event_source_unref(m->pidref_event_source);
sd_event_source_unref(m->memory_pressure_event_source);
FOREACH_ARRAY(pressure_event_source, m->pressure_event_source, _PRESSURE_RESOURCE_MAX)
sd_event_source_unref(*pressure_event_source);
safe_close(m->signal_fd);
safe_close(m->notify_fd);
@@ -4300,8 +4316,7 @@ int manager_set_unit_defaults(Manager *m, const UnitDefaults *defaults) {
m->defaults.oom_score_adjust = defaults->oom_score_adjust;
m->defaults.oom_score_adjust_set = defaults->oom_score_adjust_set;
m->defaults.memory_pressure_watch = defaults->memory_pressure_watch;
m->defaults.memory_pressure_threshold_usec = defaults->memory_pressure_threshold_usec;
memcpy(m->defaults.pressure, defaults->pressure, sizeof(m->defaults.pressure));
m->defaults.memory_zswap_writeback = defaults->memory_zswap_writeback;
@@ -5195,8 +5210,10 @@ void unit_defaults_init(UnitDefaults *defaults, RuntimeScope scope) {
.tasks_max = DEFAULT_TASKS_MAX,
.timer_accuracy_usec = 1 * USEC_PER_MINUTE,
.memory_pressure_watch = CGROUP_PRESSURE_WATCH_AUTO,
.memory_pressure_threshold_usec = MEMORY_PRESSURE_DEFAULT_THRESHOLD_USEC,
.pressure = {
[PRESSURE_MEMORY] = { .watch = CGROUP_PRESSURE_WATCH_AUTO, .threshold_usec = PRESSURE_DEFAULT_THRESHOLD_USEC },
[PRESSURE_CPU] = { .watch = CGROUP_PRESSURE_WATCH_AUTO, .threshold_usec = PRESSURE_DEFAULT_THRESHOLD_USEC },
},
.oom_policy = OOM_STOP,
.oom_score_adjust_set = false,
+3 -4
View File
@@ -149,8 +149,7 @@ typedef struct UnitDefaults {
bool memory_zswap_writeback;
CGroupPressureWatch memory_pressure_watch;
usec_t memory_pressure_threshold_usec;
CGroupPressure pressure[_PRESSURE_RESOURCE_MAX];
char *smack_process_label;
@@ -481,7 +480,7 @@ typedef struct Manager {
/* Dump*() are slow, so always rate limit them to 10 per 10 minutes */
RateLimit dump_ratelimit;
sd_event_source *memory_pressure_event_source;
sd_event_source *pressure_event_source[_PRESSURE_RESOURCE_MAX];
/* For NFTSet= */
sd_netlink *nfnl;
@@ -562,7 +561,7 @@ void manager_unwatch_pidref(Manager *m, const PidRef *pid);
unsigned manager_dispatch_load_queue(Manager *m);
int manager_setup_memory_pressure_event_source(Manager *m);
int manager_setup_pressure_event_source(Manager *m, PressureResource t);
int manager_default_environment(Manager *m);
int manager_transient_environment_add(Manager *m, char **plus);
+2
View File
@@ -78,6 +78,8 @@
#DefaultLimitRTTIME=
#DefaultMemoryPressureThresholdSec=200ms
#DefaultMemoryPressureWatch=auto
#DefaultCPUPressureThresholdSec=200ms
#DefaultCPUPressureWatch=auto
#DefaultOOMPolicy=stop
#DefaultSmackProcessLabel=
#DefaultRestrictSUIDSGID=
+2 -3
View File
@@ -178,10 +178,9 @@ static void unit_init(Unit *u) {
if (u->type != UNIT_SLICE)
cc->tasks_max = u->manager->defaults.tasks_max;
cc->memory_pressure_watch = u->manager->defaults.memory_pressure_watch;
cc->memory_pressure_threshold_usec = u->manager->defaults.memory_pressure_threshold_usec;
cc->memory_zswap_writeback = u->manager->defaults.memory_zswap_writeback;
memcpy(cc->pressure, u->manager->defaults.pressure, sizeof(cc->pressure));
}
ec = unit_get_exec_context(u);
+2
View File
@@ -54,6 +54,8 @@
#DefaultLimitRTTIME=
#DefaultMemoryPressureThresholdSec=200ms
#DefaultMemoryPressureWatch=auto
#DefaultCPUPressureThresholdSec=200ms
#DefaultCPUPressureWatch=auto
#DefaultSmackProcessLabel=
#DefaultRestrictSUIDSGID=
#ReloadLimitIntervalSec=
+4 -2
View File
@@ -323,8 +323,10 @@ int unit_cgroup_context_build_json(sd_json_variant **ret, const char *name, void
JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("ManagedOOMMemoryPressureLimit", c->moom_mem_pressure_limit),
JSON_BUILD_PAIR_FINITE_USEC("ManagedOOMMemoryPressureDurationUSec", c->moom_mem_pressure_duration_usec),
SD_JSON_BUILD_PAIR_STRING("ManagedOOMPreference", managed_oom_preference_to_string(c->moom_preference)),
SD_JSON_BUILD_PAIR_STRING("MemoryPressureWatch", cgroup_pressure_watch_to_string(c->memory_pressure_watch)),
JSON_BUILD_PAIR_FINITE_USEC("MemoryPressureThresholdUSec", c->memory_pressure_threshold_usec),
SD_JSON_BUILD_PAIR_STRING("MemoryPressureWatch", cgroup_pressure_watch_to_string(c->pressure[PRESSURE_MEMORY].watch)),
JSON_BUILD_PAIR_FINITE_USEC("MemoryPressureThresholdUSec", c->pressure[PRESSURE_MEMORY].threshold_usec),
SD_JSON_BUILD_PAIR_STRING("CPUPressureWatch", cgroup_pressure_watch_to_string(c->pressure[PRESSURE_CPU].watch)),
JSON_BUILD_PAIR_FINITE_USEC("CPUPressureThresholdUSec", c->pressure[PRESSURE_CPU].threshold_usec),
/* Others */
SD_JSON_BUILD_PAIR_BOOLEAN("CoredumpReceive", c->coredump_receive));
+4 -2
View File
@@ -106,8 +106,10 @@ static int manager_context_build_json(sd_json_variant **ret, const char *name, v
SD_JSON_BUILD_PAIR_BOOLEAN("DefaultTasksAccounting", m->defaults.tasks_accounting),
SD_JSON_BUILD_PAIR_CALLBACK("DefaultLimits", rlimit_table_build_json, m->defaults.rlimit),
SD_JSON_BUILD_PAIR_UNSIGNED("DefaultTasksMax", cgroup_tasks_max_resolve(&m->defaults.tasks_max)),
JSON_BUILD_PAIR_FINITE_USEC("DefaultMemoryPressureThresholdUSec", m->defaults.memory_pressure_threshold_usec),
SD_JSON_BUILD_PAIR_STRING("DefaultMemoryPressureWatch", cgroup_pressure_watch_to_string(m->defaults.memory_pressure_watch)),
JSON_BUILD_PAIR_FINITE_USEC("DefaultMemoryPressureThresholdUSec", m->defaults.pressure[PRESSURE_MEMORY].threshold_usec),
SD_JSON_BUILD_PAIR_STRING("DefaultMemoryPressureWatch", cgroup_pressure_watch_to_string(m->defaults.pressure[PRESSURE_MEMORY].watch)),
JSON_BUILD_PAIR_FINITE_USEC("DefaultCPUPressureThresholdUSec", m->defaults.pressure[PRESSURE_CPU].threshold_usec),
SD_JSON_BUILD_PAIR_STRING("DefaultCPUPressureWatch", cgroup_pressure_watch_to_string(m->defaults.pressure[PRESSURE_CPU].watch)),
JSON_BUILD_PAIR_FINITE_USEC("RuntimeWatchdogUSec", manager_get_watchdog(m, WATCHDOG_RUNTIME)),
JSON_BUILD_PAIR_FINITE_USEC("RebootWatchdogUSec", manager_get_watchdog(m, WATCHDOG_REBOOT)),
JSON_BUILD_PAIR_FINITE_USEC("KExecWatchdogUSec", manager_get_watchdog(m, WATCHDOG_KEXEC)),
+1 -2
View File
@@ -1949,8 +1949,7 @@ static int event_add_pressure(
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_origin_changed(e), -ECHILD);
assert(resource >= 0 && resource < _PRESSURE_RESOURCE_MAX);
const PressureResourceInfo *info = &pressure_resource_info[resource];
const PressureResourceInfo *info = pressure_resource_get_info(resource);
if (!callback)
callback = default_callback;
+2
View File
@@ -2383,6 +2383,7 @@ static const BusProperty cgroup_properties[] = {
{ "ManagedOOMMemoryPressure", bus_append_string },
{ "ManagedOOMPreference", bus_append_string },
{ "MemoryPressureWatch", bus_append_string },
{ "CPUPressureWatch", bus_append_string },
{ "DelegateSubgroup", bus_append_string },
{ "ManagedOOMMemoryPressureLimit", bus_append_parse_permyriad },
{ "MemoryAccounting", bus_append_parse_boolean },
@@ -2421,6 +2422,7 @@ static const BusProperty cgroup_properties[] = {
{ "SocketBindAllow", bus_append_socket_filter },
{ "SocketBindDeny", bus_append_socket_filter },
{ "MemoryPressureThresholdSec", bus_append_parse_sec_rename },
{ "CPUPressureThresholdSec", bus_append_parse_sec_rename },
{ "NFTSet", bus_append_nft_set },
{ "BindNetworkInterface", bus_append_string },
+4
View File
@@ -64,6 +64,10 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_DEFINE_FIELD(DefaultMemoryPressureThresholdUSec, SD_VARLINK_INT, 0),
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultMemoryPressureWatch="),
SD_VARLINK_DEFINE_FIELD(DefaultMemoryPressureWatch, SD_VARLINK_STRING, 0),
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultCPUPressureThresholdUSec="),
SD_VARLINK_DEFINE_FIELD(DefaultCPUPressureThresholdUSec, SD_VARLINK_INT, 0),
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#DefaultCPUPressureWatch="),
SD_VARLINK_DEFINE_FIELD(DefaultCPUPressureWatch, SD_VARLINK_STRING, 0),
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#RuntimeWatchdogSec="),
SD_VARLINK_DEFINE_FIELD(RuntimeWatchdogUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd-system.conf.html#RebootWatchdogSec="),
+4
View File
@@ -228,6 +228,10 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_DEFINE_FIELD(MemoryPressureWatch, SD_VARLINK_STRING, 0),
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.resource-control.html#MemoryPressureThresholdSec="),
SD_VARLINK_DEFINE_FIELD(MemoryPressureThresholdUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.resource-control.html#CPUPressureWatch="),
SD_VARLINK_DEFINE_FIELD(CPUPressureWatch, SD_VARLINK_STRING, 0),
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.resource-control.html#CPUPressureThresholdSec="),
SD_VARLINK_DEFINE_FIELD(CPUPressureThresholdUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
/* Others */
SD_VARLINK_FIELD_COMMENT("Reflects whether to forward coredumps for processes that crash within this cgroup"),
+1 -1
View File
@@ -91,7 +91,7 @@ foreach dirname : [
'TEST-74-AUX-UTILS',
'TEST-75-RESOLVED',
'TEST-78-SIGQUEUE',
'TEST-79-MEMPRESS',
'TEST-79-PRESSURE',
'TEST-80-NOTIFYACCESS',
'TEST-81-GENERATORS',
'TEST-82-SOFTREBOOT',
@@ -13,7 +13,7 @@ if ! cat /proc/pressure/memory >/dev/null ; then
exit 0
fi
CGROUP=/sys/fs/cgroup/"$(systemctl show TEST-79-MEMPRESS.service -P ControlGroup)"
CGROUP=/sys/fs/cgroup/"$(systemctl show TEST-79-PRESSURE.service -P ControlGroup)"
test -d "$CGROUP"
if ! test -f "$CGROUP"/memory.pressure ; then
@@ -61,4 +61,57 @@ systemd-run \
rm "$SCRIPT"
# Now test CPU pressure
if ! cat /proc/pressure/cpu >/dev/null ; then
echo "kernel has no CPU PSI support." >&2
echo OK >/testok
exit 0
fi
if ! test -f "$CGROUP"/cpu.pressure ; then
echo "No CPU accounting/PSI delegated via cgroup, can't test." >&2
echo OK >/testok
exit 0
fi
UNIT="test-cpupress-$RANDOM.service"
SCRIPT="/tmp/cpupress-$RANDOM.sh"
cat >"$SCRIPT" <<'EOF'
#!/usr/bin/env bash
set -ex
export
id
test -n "$CPU_PRESSURE_WATCH"
test "$CPU_PRESSURE_WATCH" != /dev/null
test -w "$CPU_PRESSURE_WATCH"
ls -al "$CPU_PRESSURE_WATCH"
EXPECTED="$(echo -n -e "some 123000 2000000\x00" | base64)"
test "$EXPECTED" = "$CPU_PRESSURE_WRITE"
EOF
chmod +x "$SCRIPT"
systemd-run \
-u "$UNIT" \
-p Type=exec \
-p ProtectControlGroups=1 \
-p DynamicUser=1 \
-p CPUPressureWatch=on \
-p CPUPressureThresholdSec=123ms \
-p BindPaths=$SCRIPT \
`# Make sanitizers happy when DynamicUser=1 pulls in instrumented systemd NSS modules` \
-p EnvironmentFile=-/usr/lib/systemd/systemd-asan-env \
--wait "$SCRIPT"
rm "$SCRIPT"
touch /testok