Merge pull request #15206 from anitazha/systoomd-v0

systemd-oomd
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2020-10-15 14:16:52 +02:00
committed by GitHub
66 changed files with 3421 additions and 11 deletions

View File

@@ -270,6 +270,9 @@ All cgroup/resource control settings are available for transient units
✓ IPAccounting=
✓ IPAddressAllow=
✓ IPAddressDeny=
✓ ManagedOOMSwap=
✓ ManagedOOMMemoryPressure=
✓ ManagedOOMMemoryPressureLimitPercent=
```
## Process Killing Settings

86
man/oomctl.xml Normal file
View File

@@ -0,0 +1,86 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!-- SPDX-License-Identifier: LGPL-2.1+ -->
<refentry id="oomctl" conditional='ENABLE_OOMD'
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>oomctl</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>oomctl</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>oomctl</refname>
<refpurpose>Analyze the state stored in <command>systemd-oomd</command></refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>oomctl</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
<arg choice="req">COMMAND</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><command>oomctl</command> may be used to get information about the various contexts read in by
the <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry> userspace
out-of-memory (OOM) killer,
<citerefentry><refentrytitle>systemd-oomd</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
</refsect1>
<refsect1>
<title>Commands</title>
<para>The following commands are understood:</para>
<variablelist>
<varlistentry>
<term><command>dump</command></term>
<listitem><para>Show the current state of the cgroup(s) and system context(s) stored by
<command>systemd-oomd</command>.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Options</title>
<para>The following options are understood:</para>
<variablelist>
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
<xi:include href="standard-options.xml" xpointer="no-pager" />
</variablelist>
</refsect1>
<refsect1>
<title>Exit status</title>
<para>On success, 0 is returned, a non-zero failure code otherwise.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-oomd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>oomd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

88
man/oomd.conf.xml Normal file
View File

@@ -0,0 +1,88 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!-- SPDX-License-Identifier: LGPL-2.1+ -->
<refentry id="oomd.conf" conditional='ENABLE_OOMD'
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>oomd.conf</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>oomd.conf</refentrytitle>
<manvolnum>5</manvolnum>
</refmeta>
<refnamediv>
<refname>oomd.conf</refname>
<refname>oomd.conf.d</refname>
<refpurpose>Global <command>systemd-oomd</command> configuration files</refpurpose>
</refnamediv>
<refsynopsisdiv>
<para><filename>/etc/systemd/oomd.conf</filename></para>
<para><filename>/etc/systemd/oomd.conf.d/*.conf</filename></para>
<para><filename>/usr/lib/systemd/oomd.conf.d/*.conf</filename></para>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>These files configure the various parameters of the
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry> userspace
out-of-memory (OOM) killer,
<citerefentry><refentrytitle>systemd-oomd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
See <citerefentry><refentrytitle>systemd.syntax</refentrytitle><manvolnum>7</manvolnum></citerefentry>
for a general description of the syntax.</para>
</refsect1>
<xi:include href="standard-conf.xml" xpointer="main-conf" />
<refsect1>
<title>[OOM] Section Options</title>
<para>The following options are available in the [OOM] section:</para>
<variablelist class='config-directives'>
<varlistentry>
<term><varname>SwapUsedLimitPercent=</varname></term>
<listitem><para>Sets the limit for swap usage on the system before <command>systemd-oomd</command> will
take action. If the percentage of swap used on the system is more than what is defined here,
<command>systemd-oomd</command> will act on eligible descendant cgroups, starting from the ones with the
highest swap usage to the lowest swap usage. Which cgroups are monitored and what
action gets taken depends on what the unit has configured for <varname>ManagedOOMSwap=</varname>.
Takes a percentage value between 0% and 100%, inclusive. Defaults to 90%.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>DefaultMemoryPressureLimitPercent=</varname></term>
<listitem><para>Sets the limit for memory pressure on the unit's cgroup before <command>systemd-oomd</command>
will take action. A unit can override this value with <varname>ManagedOOMMemoryPressureLimitPercent=</varname>.
The memory pressure for this property represents the fraction of time in a 10 second window in which all tasks
in the cgroup were delayed. For each monitored cgroup, if the memory pressure on that cgroup exceeds the
limit set for more than 30 seconds, <command>systemd-oomd</command> will act on eligible descendant cgroups,
starting from the ones with the most reclaim activity to the least reclaim activity. Which cgroups are
monitored and what action gets taken depends on what the unit has configured for
<varname>ManagedOOMMemoryPressure=</varname>. Takes a percentage value between 0% and 100%, inclusive.
Defaults to 60%.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-oomd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>oomctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@@ -2414,6 +2414,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMSwap = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressureLimitPercent = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@@ -2928,6 +2934,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<!--property DisableControllers is not documented!-->
<!--property ManagedOOMSwap is not documented!-->
<!--property ManagedOOMMemoryPressure is not documented!-->
<!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
<!--property EnvironmentFiles is not documented!-->
<!--property PassEnvironment is not documented!-->
@@ -3478,6 +3490,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<variablelist class="dbus-property" generated="True" extra-ref="DisableControllers"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMSwap"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPercent"/>
<variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
<variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/>
@@ -4121,6 +4139,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMSwap = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressureLimitPercent = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@@ -4661,6 +4685,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<!--property DisableControllers is not documented!-->
<!--property ManagedOOMSwap is not documented!-->
<!--property ManagedOOMMemoryPressure is not documented!-->
<!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
<!--property EnvironmentFiles is not documented!-->
<!--property PassEnvironment is not documented!-->
@@ -5211,6 +5241,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<variablelist class="dbus-property" generated="True" extra-ref="DisableControllers"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMSwap"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPercent"/>
<variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
<variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/>
@@ -5780,6 +5816,12 @@ node /org/freedesktop/systemd1/unit/home_2emount {
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMSwap = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressureLimitPercent = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@@ -6250,6 +6292,12 @@ node /org/freedesktop/systemd1/unit/home_2emount {
<!--property DisableControllers is not documented!-->
<!--property ManagedOOMSwap is not documented!-->
<!--property ManagedOOMMemoryPressure is not documented!-->
<!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
<!--property EnvironmentFiles is not documented!-->
<!--property PassEnvironment is not documented!-->
@@ -6720,6 +6768,12 @@ node /org/freedesktop/systemd1/unit/home_2emount {
<variablelist class="dbus-property" generated="True" extra-ref="DisableControllers"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMSwap"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPercent"/>
<variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
<variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/>
@@ -7404,6 +7458,12 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMSwap = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressureLimitPercent = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@@ -7860,6 +7920,12 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
<!--property DisableControllers is not documented!-->
<!--property ManagedOOMSwap is not documented!-->
<!--property ManagedOOMMemoryPressure is not documented!-->
<!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
<!--property EnvironmentFiles is not documented!-->
<!--property PassEnvironment is not documented!-->
@@ -8316,6 +8382,12 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
<variablelist class="dbus-property" generated="True" extra-ref="DisableControllers"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMSwap"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPercent"/>
<variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
<variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/>
@@ -8859,6 +8931,12 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMSwap = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressureLimitPercent = '...';
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
@@ -8989,6 +9067,12 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
<!--property DisableControllers is not documented!-->
<!--property ManagedOOMSwap is not documented!-->
<!--property ManagedOOMMemoryPressure is not documented!-->
<!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
<!--Autogenerated cross-references for systemd.directives, do not edit-->
<variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.systemd1.Unit"/>
@@ -9123,6 +9207,12 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
<variablelist class="dbus-property" generated="True" extra-ref="DisableControllers"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMSwap"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPercent"/>
<!--End of Autogenerated section-->
<refsect2>
@@ -9276,6 +9366,12 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMSwap = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressureLimitPercent = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s KillMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@@ -9422,6 +9518,12 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
<!--property DisableControllers is not documented!-->
<!--property ManagedOOMSwap is not documented!-->
<!--property ManagedOOMMemoryPressure is not documented!-->
<!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
<!--property KillMode is not documented!-->
<!--property KillSignal is not documented!-->
@@ -9582,6 +9684,12 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
<variablelist class="dbus-property" generated="True" extra-ref="DisableControllers"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMSwap"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPercent"/>
<variablelist class="dbus-property" generated="True" extra-ref="KillMode"/>
<variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/>

View File

@@ -45,6 +45,8 @@ manpages = [
['nss-mymachines', '8', ['libnss_mymachines.so.2'], 'ENABLE_NSS_MYMACHINES'],
['nss-resolve', '8', ['libnss_resolve.so.2'], 'ENABLE_NSS_RESOLVE'],
['nss-systemd', '8', ['libnss_systemd.so.2'], 'ENABLE_NSS_SYSTEMD'],
['oomctl', '1', [], 'ENABLE_OOMD'],
['oomd.conf', '5', ['oomd.conf.d'], 'ENABLE_OOMD'],
['org.freedesktop.LogControl1', '5', [], ''],
['org.freedesktop.home1', '5', [], 'ENABLE_HOMED'],
['org.freedesktop.hostname1', '5', [], 'ENABLE_HOSTNAMED'],
@@ -907,6 +909,7 @@ manpages = [
['systemd-networkd.service', '8', ['systemd-networkd'], 'ENABLE_NETWORKD'],
['systemd-notify', '1', [], ''],
['systemd-nspawn', '1', [], ''],
['systemd-oomd.service', '8', ['systemd-oomd'], 'ENABLE_OOMD'],
['systemd-path', '1', [], ''],
['systemd-portabled.service', '8', ['systemd-portabled'], 'ENABLE_PORTABLED'],
['systemd-pstore.service', '8', ['systemd-pstore'], 'ENABLE_PSTORE'],

View File

@@ -0,0 +1,98 @@
<?xml version='1.0'?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!-- SPDX-License-Identifier: LGPL-2.1+ -->
<refentry id="systemd-oomd.service" conditional='ENABLE_OOMD'>
<refentryinfo>
<title>systemd-oomd.service</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>systemd-oomd.service</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
<refname>systemd-oomd.service</refname>
<refname>systemd-oomd</refname>
<refpurpose>A userspace out-of-memory (OOM) killer</refpurpose>
</refnamediv>
<refsynopsisdiv>
<para><filename>systemd-oomd.service</filename></para>
<para><filename>/usr/lib/systemd/systemd-oomd</filename></para>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><command>systemd-oomd</command> is a system service that uses cgroups-v2 and pressure stall information (PSI)
to monitor and take action on processes before an OOM occurs in kernel space.</para>
<para>You can enable monitoring and actions on units by setting <varname>ManagedOOMSwap=</varname> and/or
<varname>ManagedOOMMemoryPressure=</varname> to the appropriate value. <command>systemd-oomd</command> will
periodically poll enabled units' cgroup data to detect when corrective action needs to occur. When an action needs
to happen, it will only be performed on the descendant cgroups of the enabled units. More precisely, only cgroups with
<filename>memory.oom.group</filename> set to <constant>1</constant> and leaf cgroup nodes are eligible candidates.
Action will be taken recursively on all of the processes under the chosen candidate.</para>
<para>See
<citerefentry><refentrytitle>oomd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for more information about the configuration of this service.</para>
</refsect1>
<refsect1>
<title>Setup Information</title>
<para>The system must be running systemd with a full unified cgroup hierarchy for the expected cgroups-v2 features.
Furthermore, resource accounting must be turned on for all units monitored by <command>systemd-oomd</command>.
The easiest way to turn on resource accounting is by ensuring the values for <varname>DefaultCPUAccounting</varname>,
<varname>DefaultIOAccounting</varname>, <varname>DefaultMemoryAccounting</varname>, and
<varname>DefaultTasksAccounting</varname> are set to <constant>true</constant> in
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
<para>You will need a kernel compiled with PSI support. This is available in Linux 4.20 and above.</para>
<para>The system must also have swap enabled for <command>systemd-oomd</command> to function correctly. With swap
enabled, the system spends enough time swapping pages to let <command>systemd-oomd</command> react.
Without swap, the system enters a livelocked state much more quickly and may prevent <command>systemd-oomd</command>
from responding in a reasonable amount of time. See
<ulink url="https://chrisdown.name/2018/01/02/in-defence-of-swap.html">"In defence of swap: common misconceptions"</ulink>
for more details on swap.</para>
<para>Be aware that if you intend to enable monitoring and actions on <filename>user.slice</filename>,
<filename>user-$UID.slice</filename>, or their ancestor cgroups, it is highly recommended that your programs be
managed by the systemd user manager to prevent running too many processes under the same session scope (and thus
avoid a situation where memory intensive tasks trigger <command>systemd-oomd</command> to kill everything under the
cgroup). If you're using a desktop environment like GNOME, it already spawns many session components with the
systemd user manager.</para>
</refsect1>
<refsect1>
<title>Usage Recommendations</title>
<para><varname>ManagedOOMSwap=</varname> works with the system-wide swap values, so setting it on the root slice
<filename>-.slice</filename>, and allowing all descendant cgroups to be eligible candidates may make the most
sense.</para>
<para><varname>ManagedOOMMemoryPressure=</varname> tends to work better on the cgroups below the root slice
<filename>-.slice</filename>. For units which tend to have processes that are less latency sensitive (e.g.
<filename>system.slice</filename>), a higher limit like the default of 60% may be acceptable, as those processes
can usually ride out slowdowns caused by lack of memory without serious consequences. However, something like
<filename>user@$UID.service</filename> may prefer a much lower value like 40%.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>oomd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>oomctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@@ -869,6 +869,49 @@ DeviceAllow=/dev/loop-control
<xi:include href="supported-controllers.xml" xpointer="controllers-text" />
</listitem>
</varlistentry>
<varlistentry>
<term><varname>ManagedOOMSwap=auto|kill</varname></term>
<term><varname>ManagedOOMMemoryPressure=auto|kill</varname></term>
<listitem>
<para>Specifies how
<citerefentry><refentrytitle>systemd-oomd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
will act on this unit's cgroups. Defaults to <option>auto</option>.</para>
<para>When set to <option>kill</option>, <command>systemd-oomd</command> will actively monitor this unit's
cgroup metrics to decide whether it needs to act. If the cgroup passes the limits set by
<citerefentry><refentrytitle>oomd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> or its
overrides, <command>systemd-oomd</command> will send a <constant>SIGKILL</constant> to all of the processes
under the chosen candidate cgroup. Note that only descendant cgroups can be eligible candidates for killing;
the unit that set its property to <option>kill</option> is not a candidate (unless one of its ancestors set
their property to <option>kill</option>). You can find more details on candidates and kill behavior at
<citerefentry><refentrytitle>systemd-oomd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
and <citerefentry><refentrytitle>oomd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>. Setting
either of these properties to <option>kill</option> will also automatically acquire
<varname>After=</varname> and <varname>Wants=</varname> dependencies on
<filename>systemd-oomd.service</filename> unless <varname>DefaultDependencies=no</varname>.
</para>
<para>When set to <option>auto</option>, <command>systemd-oomd</command> will not actively use this cgroup's
data for monitoring and detection. However, if an ancestor cgroup has one of these properties set to
<option>kill</option>, a unit with <option>auto</option> can still be an eligible candidate for
<command>systemd-oomd</command> to act on.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>ManagedOOMMemoryPressureLimitPercent=</varname></term>
<listitem>
<para>Overrides the default memory pressure limit set by
<citerefentry><refentrytitle>oomd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> for this unit
(cgroup). Takes a percentage value between 0% and 100%, inclusive. This property is ignored unless
<varname>ManagedOOMMemoryPressure=</varname><option>kill</option>. Defaults to 0%, which means use the
default set by <citerefentry><refentrytitle>oomd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
@@ -1030,6 +1073,7 @@ DeviceAllow=/dev/loop-control
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-oomd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
The documentation for control groups and specific controllers in the Linux kernel:
<ulink url="https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html">Control Groups v2</ulink>.
</para>

View File

@@ -1412,6 +1412,9 @@ conf.set10('ENABLE_HOMED', have)
have = have and conf.get('HAVE_PAM') == 1
conf.set10('ENABLE_PAM_HOME', have)
have = get_option('oomd') and get_option('mode') == 'developer'
conf.set10('ENABLE_OOMD', have)
want_remote = get_option('remote')
if want_remote != 'false'
have_deps = [conf.get('HAVE_MICROHTTPD') == 1,
@@ -1451,6 +1454,7 @@ foreach term : ['analyze',
'networkd',
'nss-myhostname',
'nss-systemd',
'oomd',
'portabled',
'pstore',
'quotacheck',
@@ -1671,6 +1675,7 @@ subdir('src/analyze')
subdir('src/journal-remote')
subdir('src/coredump')
subdir('src/pstore')
subdir('src/oom')
subdir('src/hostname')
subdir('src/import')
subdir('src/partition')
@@ -2730,6 +2735,27 @@ if conf.get('ENABLE_PSTORE') == 1
install_dir : rootlibexecdir)
endif
if conf.get('ENABLE_OOMD') == 1
executable('systemd-oomd',
systemd_oomd_sources,
include_directories : includes,
link_with : [libshared],
dependencies : [],
install_rpath : rootlibexecdir,
install : true,
install_dir : rootlibexecdir)
public_programs += executable(
'oomctl',
oomctl_sources,
include_directories : includes,
link_with : [libshared],
dependencies : [],
install_rpath : rootlibexecdir,
install : true,
install_dir : rootbindir)
endif
if conf.get('ENABLE_BINFMT') == 1
public_programs += executable(
'systemd-binfmt',
@@ -3748,6 +3774,7 @@ foreach tuple : [
['DNS-over-TLS(openssl)', conf.get('DNS_OVER_TLS_USE_OPENSSL') == 1],
['coredump'],
['pstore'],
['oomd'],
['polkit'],
['legacy pkla', install_polkit_pkla],
['efi'],

View File

@@ -97,6 +97,8 @@ option('coredump', type : 'boolean',
description : 'install the coredump handler')
option('pstore', type : 'boolean',
description : 'install the pstore archival tool')
option('oomd', type : 'boolean', value : 'false',
description : 'install the userspace oom killer')
option('logind', type : 'boolean',
description : 'install the systemd-logind stack')
option('hostnamed', type : 'boolean',

View File

@@ -1685,6 +1685,26 @@ int cg_get_attribute_as_uint64(const char *controller, const char *path, const c
return 0;
}
int cg_get_attribute_as_bool(const char *controller, const char *path, const char *attribute, bool *ret) {
_cleanup_free_ char *value = NULL;
int r;
assert(ret);
r = cg_get_attribute(controller, path, attribute, &value);
if (r == -ENOENT)
return -ENODATA;
if (r < 0)
return r;
r = parse_boolean(value);
if (r < 0)
return r;
*ret = r;
return 0;
}
int cg_get_keyed_attribute_full(
const char *controller,
const char *path,
@@ -2161,3 +2181,10 @@ CGroupMask get_cpu_accounting_mask(void) {
bool cpu_accounting_is_cheap(void) {
return get_cpu_accounting_mask() == 0;
}
static const char* const managed_oom_mode_table[_MANAGED_OOM_MODE_MAX] = {
[MANAGED_OOM_AUTO] = "auto",
[MANAGED_OOM_KILL] = "kill",
};
DEFINE_STRING_TABLE_LOOKUP(managed_oom_mode, ManagedOOMMode);

View File

@@ -208,6 +208,9 @@ static inline int cg_get_keyed_attribute_graceful(
int cg_get_attribute_as_uint64(const char *controller, const char *path, const char *attribute, uint64_t *ret);
/* Does a parse_boolean() on the attribute contents and sets ret accordingly */
int cg_get_attribute_as_bool(const char *controller, const char *path, const char *attribute, bool *ret);
int cg_set_access(const char *controller, const char *path, uid_t uid, gid_t gid);
int cg_set_xattr(const char *controller, const char *path, const char *name, const void *value, size_t size, int flags);
@@ -275,3 +278,13 @@ CGroupController cgroup_controller_from_string(const char *s) _pure_;
bool is_cgroup_fs(const struct statfs *s);
bool fd_is_cgroup_fs(int fd);
typedef enum ManagedOOMMode {
MANAGED_OOM_AUTO,
MANAGED_OOM_KILL,
_MANAGED_OOM_MODE_MAX,
_MANAGED_OOM_MODE_INVALID = -1,
} ManagedOOMMode;
const char* managed_oom_mode_to_string(ManagedOOMMode m) _const_;
ManagedOOMMode managed_oom_mode_from_string(const char *s) _pure_;

View File

@@ -63,3 +63,5 @@
.un.sun_family = AF_UNIX, \
.un.sun_path = "\0/org/freedesktop/plymouthd", \
}
#define VARLINK_ADDR_PATH_MANAGED_OOM "/run/systemd/io.system.ManagedOOM"

48
src/basic/linux/loadavg.h Normal file
View File

@@ -0,0 +1,48 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_SCHED_LOADAVG_H
#define _LINUX_SCHED_LOADAVG_H
/*
* These are the constant used to fake the fixed-point load-average
* counting. Some notes:
* - 11 bit fractions expand to 22 bits by the multiplies: this gives
* a load-average precision of 10 bits integer + 11 bits fractional
* - if you want to count load-averages more often, you need more
* precision, or rounding will get you. With 2-second counting freq,
* the EXP_n values would be 1981, 2034 and 2043 if still using only
* 11 bit fractions.
*/
extern unsigned long avenrun[]; /* Load averages */
extern void get_avenrun(unsigned long *loads, unsigned long offset, int shift);
#define FSHIFT 11 /* nr of bits of precision */
#define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point */
#define LOAD_FREQ (5*HZ+1) /* 5 sec intervals */
#define EXP_1 1884 /* 1/exp(5sec/1min) as fixed-point */
#define EXP_5 2014 /* 1/exp(5sec/5min) */
#define EXP_15 2037 /* 1/exp(5sec/15min) */
/*
* a1 = a0 * e + a * (1 - e)
*/
static inline unsigned long
calc_load(unsigned long load, unsigned long exp, unsigned long active)
{
unsigned long newload;
newload = load * exp + active * (FIXED_1 - exp);
if (active >= load)
newload += FIXED_1-1;
return newload / FIXED_1;
}
extern unsigned long calc_load_n(unsigned long load, unsigned long exp,
unsigned long active, unsigned int n);
#define LOAD_INT(x) ((x) >> FSHIFT)
#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
extern void calc_global_load(unsigned long ticks);
#endif /* _LINUX_SCHED_LOADAVG_H */

View File

@@ -111,6 +111,7 @@ basic_sources = files('''
linux/ipv6_route.h
linux/l2tp.h
linux/libc-compat.h
linux/loadavg.h
linux/netdevice.h
linux/netlink.h
linux/rtnetlink.h

View File

@@ -862,3 +862,45 @@ int parse_oom_score_adjust(const char *s, int *ret) {
*ret = v;
return 0;
}
int store_loadavg_fixed_point(unsigned long i, unsigned long f, loadavg_t *ret) {
assert(ret);
if (i >= (~0UL << FSHIFT))
return -ERANGE;
i = i << FSHIFT;
f = DIV_ROUND_UP((f << FSHIFT), 100);
if (f >= FIXED_1)
return -ERANGE;
*ret = i | f;
return 0;
}
int parse_loadavg_fixed_point(const char *s, loadavg_t *ret) {
const char *d, *f_str, *i_str;
unsigned long i, f;
int r;
assert(s);
assert(ret);
d = strchr(s, '.');
if (!d)
return -EINVAL;
i_str = strndupa(s, d - s);
f_str = d + 1;
r = safe_atolu_full(i_str, 10, &i);
if (r < 0)
return r;
r = safe_atolu_full(f_str, 10, &f);
if (r < 0)
return r;
return store_loadavg_fixed_point(i, f, ret);
}

View File

@@ -3,12 +3,15 @@
#include <inttypes.h>
#include <limits.h>
#include <linux/loadavg.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
#include "macro.h"
typedef unsigned long loadavg_t;
int parse_boolean(const char *v) _pure_;
int parse_dev(const char *s, dev_t *ret);
int parse_pid(const char *s, pid_t* ret_pid);
@@ -88,18 +91,18 @@ static inline int safe_atoux64(const char *s, uint64_t *ret) {
}
#if LONG_MAX == INT_MAX
static inline int safe_atolu(const char *s, unsigned long *ret_u) {
static inline int safe_atolu_full(const char *s, unsigned base, long unsigned *ret_u) {
assert_cc(sizeof(unsigned long) == sizeof(unsigned));
return safe_atou(s, (unsigned*) ret_u);
return safe_atou_full(s, base, (unsigned*) ret_u);
}
static inline int safe_atoli(const char *s, long int *ret_u) {
assert_cc(sizeof(long int) == sizeof(int));
return safe_atoi(s, (int*) ret_u);
}
#else
static inline int safe_atolu(const char *s, unsigned long *ret_u) {
static inline int safe_atolu_full(const char *s, unsigned base, unsigned long *ret_u) {
assert_cc(sizeof(unsigned long) == sizeof(unsigned long long));
return safe_atollu(s, (unsigned long long*) ret_u);
return safe_atollu_full(s, base, (unsigned long long*) ret_u);
}
static inline int safe_atoli(const char *s, long int *ret_u) {
assert_cc(sizeof(long int) == sizeof(long long int));
@@ -107,6 +110,10 @@ static inline int safe_atoli(const char *s, long int *ret_u) {
}
#endif
static inline int safe_atolu(const char *s, unsigned long *ret_u) {
return safe_atolu_full(s, 0, ret_u);
}
#if SIZE_MAX == UINT_MAX
static inline int safe_atozu(const char *s, size_t *ret_u) {
assert_cc(sizeof(size_t) == sizeof(unsigned));
@@ -137,3 +144,8 @@ int parse_ip_port_range(const char *s, uint16_t *low, uint16_t *high);
int parse_ip_prefix_length(const char *s, int *ret);
int parse_oom_score_adjust(const char *s, int *ret);
/* Given a Linux load average (e.g. decimal number 34.89 where 34 is passed as i and 89 is passed as f), convert it
* to a loadavg_t. */
int store_loadavg_fixed_point(unsigned long i, unsigned long f, loadavg_t *ret);
int parse_loadavg_fixed_point(const char *s, loadavg_t *ret);

View File

@@ -128,6 +128,9 @@ void cgroup_context_init(CGroupContext *c) {
.startup_blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID,
.tasks_max = TASKS_MAX_UNSET,
.moom_swap = MANAGED_OOM_AUTO,
.moom_mem_pressure = MANAGED_OOM_AUTO,
};
}
@@ -411,7 +414,10 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
"%sTasksMax: %" PRIu64 "\n"
"%sDevicePolicy: %s\n"
"%sDisableControllers: %s\n"
"%sDelegate: %s\n",
"%sDelegate: %s\n"
"%sManagedOOMSwap: %s\n"
"%sManagedOOMMemoryPressure: %s\n"
"%sManagedOOMMemoryPressureLimitPercent: %d%%\n",
prefix, yes_no(c->cpu_accounting),
prefix, yes_no(c->io_accounting),
prefix, yes_no(c->blockio_accounting),
@@ -441,7 +447,10 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
prefix, tasks_max_resolve(&c->tasks_max),
prefix, cgroup_device_policy_to_string(c->device_policy),
prefix, strempty(disable_controllers_str),
prefix, yes_no(c->delegate));
prefix, yes_no(c->delegate),
prefix, managed_oom_mode_to_string(c->moom_swap),
prefix, managed_oom_mode_to_string(c->moom_mem_pressure),
prefix, c->moom_mem_pressure_limit);
if (c->delegate) {
_cleanup_free_ char *t = NULL;
@@ -2672,6 +2681,47 @@ static void unit_remove_from_cgroup_empty_queue(Unit *u) {
u->in_cgroup_empty_queue = false;
}
int unit_check_oomd_kill(Unit *u) {
_cleanup_free_ char *value = NULL;
bool increased;
uint64_t n = 0;
int r;
if (!u->cgroup_path)
return 0;
r = cg_all_unified();
if (r < 0)
return log_unit_debug_errno(u, r, "Couldn't determine whether we are in all unified mode: %m");
else if (r == 0)
return 0;
r = cg_get_xattr_malloc(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "user.systemd_oomd_kill", &value);
if (r < 0 && r != -ENODATA)
return r;
if (!isempty(value)) {
r = safe_atou64(value, &n);
if (r < 0)
return r;
}
increased = n > u->managed_oom_kill_last;
u->managed_oom_kill_last = n;
if (!increased)
return 0;
if (n > 0)
log_struct(LOG_NOTICE,
"MESSAGE_ID=" SD_MESSAGE_UNIT_OOMD_KILL_STR,
LOG_UNIT_ID(u),
LOG_UNIT_INVOCATION_ID(u),
LOG_UNIT_MESSAGE(u, "systemd-oomd killed %"PRIu64" process(es) in this unit.", n));
return 1;
}
int unit_check_oom(Unit *u) {
_cleanup_free_ char *oom_kill = NULL;
bool increased;

View File

@@ -159,6 +159,11 @@ struct CGroupContext {
/* Common */
TasksMax tasks_max;
/* Settings for systemd-oomd */
ManagedOOMMode moom_swap;
ManagedOOMMode moom_mem_pressure;
int moom_mem_pressure_limit;
};
/* Used when querying IP accounting data */
@@ -224,6 +229,7 @@ int unit_watch_cgroup(Unit *u);
int unit_watch_cgroup_memory(Unit *u);
void unit_add_to_cgroup_empty_queue(Unit *u);
int unit_check_oomd_kill(Unit *u);
int unit_check_oom(Unit *u);
int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const char *suffix_path);

View File

@@ -2,6 +2,7 @@
#include "core-varlink.h"
#include "mkdir.h"
#include "strv.h"
#include "user-util.h"
#include "varlink.h"
@@ -15,6 +16,11 @@ typedef struct LookupParameters {
const char *service;
} LookupParameters;
static const char* const managed_oom_mode_properties[] = {
"ManagedOOMSwap",
"ManagedOOMMemoryPressure",
};
static int build_user_json(const char *user_name, uid_t uid, JsonVariant **ret) {
assert(user_name);
assert(uid_is_valid(uid));
@@ -45,6 +51,150 @@ static bool user_match_lookup_parameters(LookupParameters *p, const char *name,
return true;
}
static int build_managed_oom_json_array_element(Unit *u, const char *property, JsonVariant **ret_v) {
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
CGroupContext *c;
const char *mode;
int r;
assert(u);
assert(property);
assert(ret_v);
if (!UNIT_VTABLE(u)->can_set_managed_oom)
return -EOPNOTSUPP;
c = unit_get_cgroup_context(u);
if (!c)
return -EINVAL;
if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(u)))
/* systemd-oomd should always treat inactive units as though they didn't enable any action since they
* should not have a valid cgroup */
mode = managed_oom_mode_to_string(MANAGED_OOM_AUTO);
else if (streq(property, "ManagedOOMSwap"))
mode = managed_oom_mode_to_string(c->moom_swap);
else if (streq(property, "ManagedOOMMemoryPressure"))
mode = managed_oom_mode_to_string(c->moom_mem_pressure);
else
return -EINVAL;
r = json_build(&v, JSON_BUILD_OBJECT(
JSON_BUILD_PAIR("mode", JSON_BUILD_STRING(mode)),
JSON_BUILD_PAIR("path", JSON_BUILD_STRING(u->cgroup_path)),
JSON_BUILD_PAIR("property", JSON_BUILD_STRING(property)),
JSON_BUILD_PAIR("limit", JSON_BUILD_UNSIGNED(c->moom_mem_pressure_limit))));
*ret_v = TAKE_PTR(v);
return r;
}
int manager_varlink_send_managed_oom_update(Unit *u) {
_cleanup_(json_variant_unrefp) JsonVariant *arr = NULL, *v = NULL;
CGroupContext *c;
int r;
assert(u);
if (!UNIT_VTABLE(u)->can_set_managed_oom || !u->manager || !u->manager->managed_oom_varlink_request || !u->cgroup_path)
return 0;
c = unit_get_cgroup_context(u);
if (!c)
return 0;
r = json_build(&arr, JSON_BUILD_EMPTY_ARRAY);
if (r < 0)
return r;
for (size_t i = 0; i < ELEMENTSOF(managed_oom_mode_properties); i++) {
_cleanup_(json_variant_unrefp) JsonVariant *e = NULL;
r = build_managed_oom_json_array_element(u, managed_oom_mode_properties[i], &e);
if (r < 0)
return r;
r = json_variant_append_array(&arr, e);
if (r < 0)
return r;
}
r = json_build(&v, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("cgroups", JSON_BUILD_VARIANT(arr))));
if (r < 0)
return r;
return varlink_notify(u->manager->managed_oom_varlink_request, v);
}
static int vl_method_subscribe_managed_oom_cgroups(
Varlink *link,
JsonVariant *parameters,
VarlinkMethodFlags flags,
void *userdata) {
static const UnitType supported_unit_types[] = { UNIT_SLICE, UNIT_SERVICE, UNIT_SCOPE };
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *arr = NULL;
Manager *m = userdata;
int r;
assert(link);
assert(m);
if (json_variant_elements(parameters) > 0)
return varlink_error_invalid_parameter(link, parameters);
/* We only take one subscriber for this method so return an error if there's already an existing one.
* This shouldn't happen since systemd-oomd is the only client of this method. */
if (FLAGS_SET(flags, VARLINK_METHOD_MORE) && m->managed_oom_varlink_request)
return varlink_error(m->managed_oom_varlink_request, VARLINK_ERROR_SUBSCRIPTION_TAKEN, NULL);
r = json_build(&arr, JSON_BUILD_EMPTY_ARRAY);
if (r < 0)
return r;
for (size_t i = 0; i < ELEMENTSOF(supported_unit_types); i++) {
Unit *u;
LIST_FOREACH(units_by_type, u, m->units_by_type[supported_unit_types[i]]) {
CGroupContext *c;
if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(u)))
continue;
c = unit_get_cgroup_context(u);
if (!c)
continue;
for (size_t j = 0; j < ELEMENTSOF(managed_oom_mode_properties); j++) {
_cleanup_(json_variant_unrefp) JsonVariant *e = NULL;
/* For the initial varlink call we only care about units that enabled (i.e. mode is not
* set to "auto") oomd properties. */
if (!(streq(managed_oom_mode_properties[j], "ManagedOOMSwap") && c->moom_swap == MANAGED_OOM_KILL) &&
!(streq(managed_oom_mode_properties[j], "ManagedOOMMemoryPressure") && c->moom_mem_pressure == MANAGED_OOM_KILL))
continue;
r = build_managed_oom_json_array_element(u, managed_oom_mode_properties[j], &e);
if (r < 0)
return r;
r = json_variant_append_array(&arr, e);
if (r < 0)
return r;
}
}
}
r = json_build(&v, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("cgroups", JSON_BUILD_VARIANT(arr))));
if (r < 0)
return r;
if (!FLAGS_SET(flags, VARLINK_METHOD_MORE))
return varlink_reply(link, v);
m->managed_oom_varlink_request = varlink_ref(link);
return varlink_notify(m->managed_oom_varlink_request, v);
}
static int vl_method_get_user_record(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
static const JsonDispatch dispatch_table[] = {
@@ -262,6 +412,17 @@ static int vl_method_get_memberships(Varlink *link, JsonVariant *parameters, Var
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
}
static void vl_disconnect(VarlinkServer *s, Varlink *link, void *userdata) {
Manager *m = userdata;
assert(m);
assert(s);
assert(link);
if (link == m->managed_oom_varlink_request)
m->managed_oom_varlink_request = varlink_unref(link);
}
int manager_varlink_init(Manager *m) {
_cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL;
int r;
@@ -284,16 +445,25 @@ int manager_varlink_init(Manager *m) {
s,
"io.systemd.UserDatabase.GetUserRecord", vl_method_get_user_record,
"io.systemd.UserDatabase.GetGroupRecord", vl_method_get_group_record,
"io.systemd.UserDatabase.GetMemberships", vl_method_get_memberships);
"io.systemd.UserDatabase.GetMemberships", vl_method_get_memberships,
"io.systemd.ManagedOOM.SubscribeManagedOOMCGroups", vl_method_subscribe_managed_oom_cgroups);
if (r < 0)
return log_error_errno(r, "Failed to register varlink methods: %m");
r = varlink_server_bind_disconnect(s, vl_disconnect);
if (r < 0)
return log_error_errno(r, "Failed to register varlink disconnect handler: %m");
if (!MANAGER_IS_TEST_RUN(m)) {
(void) mkdir_p_label("/run/systemd/userdb", 0755);
r = varlink_server_listen_address(s, "/run/systemd/userdb/io.systemd.DynamicUser", 0666);
if (r < 0)
return log_error_errno(r, "Failed to bind to varlink socket: %m");
r = varlink_server_listen_address(s, VARLINK_ADDR_PATH_MANAGED_OOM, 0666);
if (r < 0)
return log_error_errno(r, "Failed to bind to varlink socket: %m");
}
r = varlink_server_attach_event(s, m->event, SD_EVENT_PRIORITY_NORMAL);
@@ -307,5 +477,11 @@ int manager_varlink_init(Manager *m) {
void manager_varlink_done(Manager *m) {
assert(m);
/* Send the final message if we still have a subscribe request open. */
if (m->managed_oom_varlink_request) {
(void) varlink_error(m->managed_oom_varlink_request, VARLINK_ERROR_DISCONNECTED, NULL);
m->managed_oom_varlink_request = varlink_unref(m->managed_oom_varlink_request);
}
m->varlink_server = varlink_server_unref(m->varlink_server);
}

View File

@@ -5,3 +5,8 @@
int manager_varlink_init(Manager *m);
void manager_varlink_done(Manager *m);
/* The manager is expected to send an update to systemd-oomd if one of the following occurs:
* - The value of ManagedOOM*= properties change
* - A unit with ManagedOOM*= properties changes unit active state */
int manager_varlink_send_managed_oom_update(Unit *u);

Some files were not shown because too many files have changed in this diff Show More