mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
@@ -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
86
man/oomctl.xml
Normal 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
88
man/oomd.conf.xml
Normal 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>
|
||||
@@ -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"/>
|
||||
|
||||
@@ -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'],
|
||||
|
||||
98
man/systemd-oomd.service.xml
Normal file
98
man/systemd-oomd.service.xml
Normal 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>
|
||||
@@ -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>
|
||||
|
||||
27
meson.build
27
meson.build
@@ -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'],
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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
48
src/basic/linux/loadavg.h
Normal 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 */
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user