1
0
mirror of https://github.com/systemd/systemd synced 2025-09-30 17:24:46 +02:00

Compare commits

..

8 Commits

Author SHA1 Message Date
Yu Watanabe
7bac23e8af man: fix typo 2021-02-04 19:17:50 +01:00
Zbigniew Jędrzejewski-Szmek
29eb0eefd1 core: map io.bfq.weight to 1..1000
Aaargh. See the comment in the code.

Apparently the range is like that:
$ sudo bash -c 'echo "default 1001" >/sys/fs/cgroup/user.slice/io.bfq.weight'
bash: line 0: echo: write error: Numerical result out of range

$ uname -r
5.11.0-0.rc4.129.fc34.x86_64
2021-02-04 19:15:03 +01:00
David Edmundson
84c46fb03c xdg-autostart: Generate autostart services with templated name
The "XDG standardization for applications" specification states that
services should be in the form:

app[-<launcher>]-<ApplicationID>[@<RANDOM>].service or
app[-<launcher>]-<ApplicationID>-<RANDOM>.scope

In this case "autostart" takes the place of [RANDOM] to provide a unique
identifier if the same app is launched elsewhere. As it is a service
that means it should be set as a template not using a hyphen delimiter.
2021-02-04 16:41:22 +01:00
Daan De Meyer
bcea93326b boot: Replace efivar_set() persistent argument with flags argument
To add secure-boot enrolling support, we need to be able to specify
the EFI_VARIABLE_APPEND_WRITE flag so let's make the efivar_set()
methods more generic so we can set that flag.
2021-02-04 16:38:22 +01:00
Zbigniew Jędrzejewski-Szmek
a7a1887869 man: reword the description of "main conf file"
While not really "wrong", the text we had could use a little editing.

Fixes #18458.
2021-02-04 14:32:28 +01:00
Zbigniew Jędrzejewski-Szmek
3d0112878f
Merge pull request #18444 from anitazha/proprename
oom: parse properties with 1/10000 precision instead of 1/100
2021-02-04 12:53:10 +01:00
Anita Zhang
0a9f93443b oom: rework *MemoryPressureLimit= properties to have 1/10000 precision
Requested in
https://github.com/systemd/systemd/pull/15206#discussion_r505506657,
preserve the full granularity for memory pressure limits (permyriad)
instead of capping out at percent.
2021-02-02 17:52:48 -08:00
Anita Zhang
94a8e2d6db parse-util: add permyriad parsing 2021-02-02 01:47:08 -08:00
36 changed files with 350 additions and 231 deletions

View File

@ -272,7 +272,7 @@ All cgroup/resource control settings are available for transient units
✓ IPAddressDeny= ✓ IPAddressDeny=
✓ ManagedOOMSwap= ✓ ManagedOOMSwap=
✓ ManagedOOMMemoryPressure= ✓ ManagedOOMMemoryPressure=
✓ ManagedOOMMemoryPressureLimitPercent= ✓ ManagedOOMMemoryPressureLimit=
``` ```
## Process Killing Settings ## Process Killing Settings

View File

@ -59,10 +59,10 @@
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><varname>DefaultMemoryPressureLimitPercent=</varname></term> <term><varname>DefaultMemoryPressureLimit=</varname></term>
<listitem><para>Sets the limit for memory pressure on the unit's cgroup before <command>systemd-oomd</command> <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>. will take action. A unit can override this value with <varname>ManagedOOMMemoryPressureLimit=</varname>.
The memory pressure for this property represents the fraction of time in a 10 second window in which all tasks 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 in the cgroup were delayed. For each monitored cgroup, if the memory pressure on that cgroup exceeds the
limit set for longer than the duration set by <varname>DefaultMemoryPressureDurationSec=</varname>, limit set for longer than the duration set by <varname>DefaultMemoryPressureDurationSec=</varname>,
@ -78,7 +78,7 @@
<listitem><para>Sets the amount of time a unit's cgroup needs to have exceeded memory pressure limits before <listitem><para>Sets the amount of time a unit's cgroup needs to have exceeded memory pressure limits before
<command>systemd-oomd</command> will take action. Memory pressure limits are defined by <command>systemd-oomd</command> will take action. Memory pressure limits are defined by
<varname>DefaultMemoryPressureLimitPercent=</varname> and <varname>ManagedOOMMemoryPressureLimitPercent=</varname>. <varname>DefaultMemoryPressureLimit=</varname> and <varname>ManagedOOMMemoryPressureLimit=</varname>.
Defaults to 30 seconds when this property is unset or set to 0.</para></listitem> Defaults to 30 seconds when this property is unset or set to 0.</para></listitem>
</varlistentry> </varlistentry>

View File

@ -2449,7 +2449,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false") @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...'; readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false") @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressureLimitPercent = '...'; readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...]; readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@ -2972,7 +2972,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<!--property ManagedOOMMemoryPressure is not documented!--> <!--property ManagedOOMMemoryPressure is not documented!-->
<!--property ManagedOOMMemoryPressureLimitPercent is not documented!--> <!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
<!--property EnvironmentFiles is not documented!--> <!--property EnvironmentFiles is not documented!-->
@ -3536,7 +3536,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/> <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="ManagedOOMMemoryPressureLimitPermyriad"/>
<variablelist class="dbus-property" generated="True" extra-ref="Environment"/> <variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
@ -4203,7 +4203,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false") @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...'; readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false") @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressureLimitPercent = '...'; readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...]; readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@ -4754,7 +4754,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<!--property ManagedOOMMemoryPressure is not documented!--> <!--property ManagedOOMMemoryPressure is not documented!-->
<!--property ManagedOOMMemoryPressureLimitPercent is not documented!--> <!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
<!--property EnvironmentFiles is not documented!--> <!--property EnvironmentFiles is not documented!-->
@ -5316,7 +5316,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/> <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="ManagedOOMMemoryPressureLimitPermyriad"/>
<variablelist class="dbus-property" generated="True" extra-ref="Environment"/> <variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
@ -5896,7 +5896,7 @@ node /org/freedesktop/systemd1/unit/home_2emount {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false") @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...'; readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false") @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressureLimitPercent = '...'; readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...]; readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@ -6375,7 +6375,7 @@ node /org/freedesktop/systemd1/unit/home_2emount {
<!--property ManagedOOMMemoryPressure is not documented!--> <!--property ManagedOOMMemoryPressure is not documented!-->
<!--property ManagedOOMMemoryPressureLimitPercent is not documented!--> <!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
<!--property EnvironmentFiles is not documented!--> <!--property EnvironmentFiles is not documented!-->
@ -6855,7 +6855,7 @@ node /org/freedesktop/systemd1/unit/home_2emount {
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/> <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="ManagedOOMMemoryPressureLimitPermyriad"/>
<variablelist class="dbus-property" generated="True" extra-ref="Environment"/> <variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
@ -7556,7 +7556,7 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false") @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...'; readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false") @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressureLimitPercent = '...'; readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...]; readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@ -8021,7 +8021,7 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
<!--property ManagedOOMMemoryPressure is not documented!--> <!--property ManagedOOMMemoryPressure is not documented!-->
<!--property ManagedOOMMemoryPressureLimitPercent is not documented!--> <!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
<!--property EnvironmentFiles is not documented!--> <!--property EnvironmentFiles is not documented!-->
@ -8487,7 +8487,7 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/> <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="ManagedOOMMemoryPressureLimitPermyriad"/>
<variablelist class="dbus-property" generated="True" extra-ref="Environment"/> <variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
@ -9041,7 +9041,7 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false") @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...'; readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false") @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressureLimitPercent = '...'; readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
}; };
interface org.freedesktop.DBus.Peer { ... }; interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... }; interface org.freedesktop.DBus.Introspectable { ... };
@ -9176,7 +9176,7 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
<!--property ManagedOOMMemoryPressure is not documented!--> <!--property ManagedOOMMemoryPressure is not documented!-->
<!--property ManagedOOMMemoryPressureLimitPercent is not documented!--> <!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
<!--Autogenerated cross-references for systemd.directives, do not edit--> <!--Autogenerated cross-references for systemd.directives, do not edit-->
@ -9316,7 +9316,7 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/> <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="ManagedOOMMemoryPressureLimitPermyriad"/>
<!--End of Autogenerated section--> <!--End of Autogenerated section-->
@ -9476,7 +9476,7 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false") @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...'; readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false") @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressureLimitPercent = '...'; readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s KillMode = '...'; readonly s KillMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@ -9627,7 +9627,7 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
<!--property ManagedOOMMemoryPressure is not documented!--> <!--property ManagedOOMMemoryPressure is not documented!-->
<!--property ManagedOOMMemoryPressureLimitPercent is not documented!--> <!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
<!--property KillMode is not documented!--> <!--property KillMode is not documented!-->
@ -9793,7 +9793,7 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/> <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="ManagedOOMMemoryPressureLimitPermyriad"/>
<variablelist class="dbus-property" generated="True" extra-ref="KillMode"/> <variablelist class="dbus-property" generated="True" extra-ref="KillMode"/>

View File

@ -41,33 +41,30 @@
<refsection id='main-conf'> <refsection id='main-conf'>
<title>Configuration Directories and Precedence</title> <title>Configuration Directories and Precedence</title>
<para>The default configuration is defined during compilation, so a <para>The default configuration is set during compilation, so configuration is only needed when it is
configuration file is only needed when it is necessary to deviate necessary to deviate from those defaults. Initially, the main configuration file in
from those defaults. By default, the configuration file in <filename>/etc/systemd/</filename> contains commented out entries showing the defaults as a guide to the
<filename>/etc/systemd/</filename> contains commented out entries administrator. Local overrides can be created by editing this file or by creating drop-ins, see below.
showing the defaults as a guide to the administrator. This file
can be edited to create local overrides.
</para> </para>
<para>When packages need to customize the configuration, they can install configuration snippets in <para>In addition to the "main" configuration file, drop-in configuration snippets are read from
<filename>/usr/lib/systemd/*.conf.d/</filename> or <filename>/usr/local/lib/systemd/*.conf.d/</filename>. <filename>/usr/lib/systemd/*.conf.d/</filename>, <filename>/usr/local/lib/systemd/*.conf.d/</filename>,
The main configuration file is read before any of the configuration directories, and has the lowest and <filename>/etc/systemd/*.conf.d/</filename>. Those drop-ins have higher precedence and override the
precedence; entries in a file in any configuration directory override entries in the single configuration main configuration file. Files in the <filename>*.conf.d/</filename> configuration subdirectories are
file. Files in the <filename>*.conf.d/</filename> configuration subdirectories are sorted by their sorted by their filename in lexicographic order, regardless of in which of the subdirectories they
filename in lexicographic order, regardless of in which of the subdirectories they reside. When multiple reside. When multiple files specify the same option, for options which accept just a single value, the
files specify the same option, for options which accept just a single value, the entry in the file with entry in the file sorted last takes precedence, and for options which accept a list of values, entries
the lexicographically latest name takes precedence. For options which accept a list of values, entries are collected as they occur in the sorted files.</para>
are collected as they occur in files sorted lexicographically.</para>
<para>Files in <filename>/etc/</filename> are reserved for the local administrator, who may use this <para>When packages need to customize the configuration, they can install drop-ins under
logic to override the configuration files installed by vendor packages. It is recommended to prefix all <filename>/usr/</filename>. Files in <filename>/etc/</filename> are reserved for the local administrator,
filenames in those subdirectories with a two-digit number and a dash, to simplify the ordering of the who may use this logic to override the configuration files installed by vendor packages. Drop-ins have to
files.</para> be used to override package drop-ins, since the main configuration file has lower precedence. It is
recommended to prefix all filenames in those subdirectories with a two-digit number and a dash, to
simplify the ordering of the files.</para>
<para>To disable a configuration file supplied by the vendor, the <para>To disable a configuration file supplied by the vendor, the recommended way is to place a symlink
recommended way is to place a symlink to to <filename>/dev/null</filename> in the configuration directory in <filename>/etc/</filename>, with the
<filename>/dev/null</filename> in the configuration directory in same filename as the vendor configuration file.</para>
<filename>/etc/</filename>, with the same filename as the vendor
configuration file.</para>
</refsection> </refsection>
</refsection> </refsection>

View File

@ -168,7 +168,7 @@ disable *</programlisting>
</refsect1> </refsect1>
<refsect1> <refsect1>
<title>Motiviation for the preset logic</title> <title>Motivation for the preset logic</title>
<para>Different distributions have different policies on which services shall be enabled by default when <para>Different distributions have different policies on which services shall be enabled by default when
the package they are shipped in is installed. On Fedora all services stay off by default, so that the package they are shipped in is installed. On Fedora all services stay off by default, so that

View File

@ -901,7 +901,7 @@ DeviceAllow=/dev/loop-control
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><varname>ManagedOOMMemoryPressureLimitPercent=</varname></term> <term><varname>ManagedOOMMemoryPressureLimit=</varname></term>
<listitem> <listitem>
<para>Overrides the default memory pressure limit set by <para>Overrides the default memory pressure limit set by

View File

@ -627,11 +627,11 @@ int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
return 0; return 0;
} }
int parse_percent_unbounded(const char *p) { static int parse_parts_value_whole(const char *p, const char *symbol) {
const char *pc, *n; const char *pc, *n;
int r, v; int r, v;
pc = endswith(p, "%"); pc = endswith(p, symbol);
if (!pc) if (!pc)
return -EINVAL; return -EINVAL;
@ -645,30 +645,11 @@ int parse_percent_unbounded(const char *p) {
return v; return v;
} }
int parse_percent(const char *p) { static int parse_parts_value_with_tenths_place(const char *p, const char *symbol) {
int v; const char *pc, *dot, *n;
v = parse_percent_unbounded(p);
if (v > 100)
return -ERANGE;
return v;
}
int parse_permille_unbounded(const char *p) {
const char *pc, *pm, *dot, *n;
int r, q, v; int r, q, v;
pm = endswith(p, ""); pc = endswith(p, symbol);
if (pm) {
n = strndupa(p, pm - p);
r = safe_atoi(n, &v);
if (r < 0)
return r;
if (v < 0)
return -ERANGE;
} else {
pc = endswith(p, "%");
if (!pc) if (!pc)
return -EINVAL; return -EINVAL;
@ -693,11 +674,65 @@ int parse_permille_unbounded(const char *p) {
return -ERANGE; return -ERANGE;
v = v * 10 + q; v = v * 10 + q;
return v;
}
static int parse_parts_value_with_hundredths_place(const char *p, const char *symbol) {
const char *pc, *dot, *n;
int r, q, v;
pc = endswith(p, symbol);
if (!pc)
return -EINVAL;
dot = memchr(p, '.', pc - p);
if (dot) {
if (dot + 3 != pc)
return -EINVAL;
if (dot[1] < '0' || dot[1] > '9' || dot[2] < '0' || dot[2] > '9')
return -EINVAL;
q = (dot[1] - '0') * 10 + (dot[2] - '0');
n = strndupa(p, dot - p);
} else {
q = 0;
n = strndupa(p, pc - p);
} }
r = safe_atoi(n, &v);
if (r < 0)
return r;
if (v < 0)
return -ERANGE;
if (v > (INT_MAX - q) / 100)
return -ERANGE;
v = v * 100 + q;
return v;
}
int parse_percent_unbounded(const char *p) {
return parse_parts_value_whole(p, "%");
}
int parse_percent(const char *p) {
int v;
v = parse_percent_unbounded(p);
if (v > 100)
return -ERANGE;
return v; return v;
} }
int parse_permille_unbounded(const char *p) {
const char *pm;
pm = endswith(p, "");
if (pm)
return parse_parts_value_whole(p, "");
return parse_parts_value_with_tenths_place(p, "%");
}
int parse_permille(const char *p) { int parse_permille(const char *p) {
int v; int v;
@ -708,6 +743,30 @@ int parse_permille(const char *p) {
return v; return v;
} }
int parse_permyriad_unbounded(const char *p) {
const char *pm;
pm = endswith(p, "");
if (pm)
return parse_parts_value_whole(p, "");
pm = endswith(p, "");
if (pm)
return parse_parts_value_with_tenths_place(p, "");
return parse_parts_value_with_hundredths_place(p, "%");
}
int parse_permyriad(const char *p) {
int v;
v = parse_permyriad_unbounded(p);
if (v > 10000)
return -ERANGE;
return v;
}
int parse_nice(const char *p, int *ret) { int parse_nice(const char *p, int *ret) {
int n, r; int n, r;

View File

@ -133,6 +133,9 @@ int parse_percent(const char *p);
int parse_permille_unbounded(const char *p); int parse_permille_unbounded(const char *p);
int parse_permille(const char *p); int parse_permille(const char *p);
int parse_permyriad_unbounded(const char *p);
int parse_permyriad(const char *p);
int parse_nice(const char *p, int *ret); int parse_nice(const char *p, int *ret);
int parse_ip_port(const char *s, uint16_t *ret); int parse_ip_port(const char *s, uint16_t *ret);

View File

@ -765,12 +765,12 @@ static BOOLEAN menu_run(
LOADER_GUID, LOADER_GUID,
L"LoaderEntryDefault", L"LoaderEntryDefault",
config->entries[idx_highlight]->id, config->entries[idx_highlight]->id,
TRUE); EFI_VARIABLE_NON_VOLATILE);
config->idx_default_efivar = idx_highlight; config->idx_default_efivar = idx_highlight;
status = StrDuplicate(L"Default boot entry selected."); status = StrDuplicate(L"Default boot entry selected.");
} else { } else {
/* clear the default entry EFI variable */ /* clear the default entry EFI variable */
efivar_set(LOADER_GUID, L"LoaderEntryDefault", NULL, TRUE); efivar_set(LOADER_GUID, L"LoaderEntryDefault", NULL, EFI_VARIABLE_NON_VOLATILE);
config->idx_default_efivar = -1; config->idx_default_efivar = -1;
status = StrDuplicate(L"Default boot entry cleared."); status = StrDuplicate(L"Default boot entry cleared.");
} }
@ -782,14 +782,18 @@ static BOOLEAN menu_run(
if (config->timeout_sec_efivar > 0) { if (config->timeout_sec_efivar > 0) {
config->timeout_sec_efivar--; config->timeout_sec_efivar--;
efivar_set_uint_string( efivar_set_uint_string(
LOADER_GUID, L"LoaderConfigTimeout", config->timeout_sec_efivar, TRUE); LOADER_GUID,
L"LoaderConfigTimeout",
config->timeout_sec_efivar,
EFI_VARIABLE_NON_VOLATILE);
if (config->timeout_sec_efivar > 0) if (config->timeout_sec_efivar > 0)
status = PoolPrint(L"Menu timeout set to %d sec.", config->timeout_sec_efivar); status = PoolPrint(L"Menu timeout set to %d sec.", config->timeout_sec_efivar);
else else
status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu."); status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu.");
} else if (config->timeout_sec_efivar <= 0){ } else if (config->timeout_sec_efivar <= 0){
config->timeout_sec_efivar = -1; config->timeout_sec_efivar = -1;
efivar_set(LOADER_GUID, L"LoaderConfigTimeout", NULL, TRUE); efivar_set(
LOADER_GUID, L"LoaderConfigTimeout", NULL, EFI_VARIABLE_NON_VOLATILE);
if (config->timeout_sec_config > 0) if (config->timeout_sec_config > 0)
status = PoolPrint(L"Menu timeout of %d sec is defined by configuration file.", status = PoolPrint(L"Menu timeout of %d sec is defined by configuration file.",
config->timeout_sec_config); config->timeout_sec_config);
@ -803,7 +807,11 @@ static BOOLEAN menu_run(
if (config->timeout_sec_efivar == -1 && config->timeout_sec_config == 0) if (config->timeout_sec_efivar == -1 && config->timeout_sec_config == 0)
config->timeout_sec_efivar++; config->timeout_sec_efivar++;
config->timeout_sec_efivar++; config->timeout_sec_efivar++;
efivar_set_uint_string(LOADER_GUID, L"LoaderConfigTimeout", config->timeout_sec_efivar, TRUE); efivar_set_uint_string(
LOADER_GUID,
L"LoaderConfigTimeout",
config->timeout_sec_efivar,
EFI_VARIABLE_NON_VOLATILE);
if (config->timeout_sec_efivar > 0) if (config->timeout_sec_efivar > 0)
status = PoolPrint(L"Menu timeout set to %d sec.", status = PoolPrint(L"Menu timeout set to %d sec.",
config->timeout_sec_efivar); config->timeout_sec_efivar);
@ -1295,7 +1303,7 @@ static VOID config_entry_bump_counters(
/* Let's tell the OS that we renamed this file, so that it knows what to rename to the counter-less name on /* Let's tell the OS that we renamed this file, so that it knows what to rename to the counter-less name on
* success */ * success */
new_path = PoolPrint(L"%s\\%s", entry->path, entry->next_name); new_path = PoolPrint(L"%s\\%s", entry->path, entry->next_name);
efivar_set(LOADER_GUID, L"LoaderBootCountPath", new_path, FALSE); efivar_set(LOADER_GUID, L"LoaderBootCountPath", new_path, 0);
/* If the file we just renamed is the loader path, then let's update that. */ /* If the file we just renamed is the loader path, then let's update that. */
if (StrCmp(entry->loader, old_path) == 0) { if (StrCmp(entry->loader, old_path) == 0) {
@ -1470,7 +1478,7 @@ static VOID config_load_defaults(Config *config, EFI_FILE *root_dir) {
err = efivar_get_uint_string(LOADER_GUID, L"LoaderConfigTimeoutOneShot", &sec); err = efivar_get_uint_string(LOADER_GUID, L"LoaderConfigTimeoutOneShot", &sec);
if (!EFI_ERROR(err)) { if (!EFI_ERROR(err)) {
/* Unset variable now, after all it's "one shot". */ /* Unset variable now, after all it's "one shot". */
(void) efivar_set(LOADER_GUID, L"LoaderConfigTimeoutOneShot", NULL, TRUE); (void) efivar_set(LOADER_GUID, L"LoaderConfigTimeoutOneShot", NULL, EFI_VARIABLE_NON_VOLATILE);
config->timeout_sec = sec; config->timeout_sec = sec;
config->force_menu = TRUE; /* force the menu when this is set */ config->force_menu = TRUE; /* force the menu when this is set */
@ -1592,7 +1600,7 @@ static VOID config_default_entry_select(Config *config) {
if (!EFI_ERROR(err)) { if (!EFI_ERROR(err)) {
config->entry_oneshot = StrDuplicate(entry_oneshot); config->entry_oneshot = StrDuplicate(entry_oneshot);
efivar_set(LOADER_GUID, L"LoaderEntryOneShot", NULL, TRUE); efivar_set(LOADER_GUID, L"LoaderEntryOneShot", NULL, EFI_VARIABLE_NON_VOLATILE);
i = config_entry_find(config, entry_oneshot); i = config_entry_find(config, entry_oneshot);
if (i >= 0) { if (i >= 0) {
@ -2276,7 +2284,7 @@ static EFI_STATUS reboot_into_firmware(VOID) {
if (!EFI_ERROR(err)) if (!EFI_ERROR(err))
new |= old; new |= old;
err = efivar_set_uint64_le(EFI_GLOBAL_GUID, L"OsIndications", new, TRUE); err = efivar_set_uint64_le(EFI_GLOBAL_GUID, L"OsIndications", new, EFI_VARIABLE_NON_VOLATILE);
if (EFI_ERROR(err)) if (EFI_ERROR(err))
return err; return err;
@ -2315,7 +2323,7 @@ static VOID config_write_entries_to_variable(Config *config) {
} }
/* Store the full list of discovered entries. */ /* Store the full list of discovered entries. */
(void) efivar_set_raw(LOADER_GUID, L"LoaderEntries", buffer, (UINT8*) p - (UINT8*) buffer, FALSE); (void) efivar_set_raw(LOADER_GUID, L"LoaderEntries", buffer, (UINT8 *) p - (UINT8 *) buffer, 0);
} }
EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
@ -2343,15 +2351,15 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
InitializeLib(image, sys_table); InitializeLib(image, sys_table);
init_usec = time_usec(); init_usec = time_usec();
efivar_set_time_usec(LOADER_GUID, L"LoaderTimeInitUSec", init_usec); efivar_set_time_usec(LOADER_GUID, L"LoaderTimeInitUSec", init_usec);
efivar_set(LOADER_GUID, L"LoaderInfo", L"systemd-boot " GIT_VERSION, FALSE); efivar_set(LOADER_GUID, L"LoaderInfo", L"systemd-boot " GIT_VERSION, 0);
infostr = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); infostr = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
efivar_set(LOADER_GUID, L"LoaderFirmwareInfo", infostr, FALSE); efivar_set(LOADER_GUID, L"LoaderFirmwareInfo", infostr, 0);
typestr = PoolPrint(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); typestr = PoolPrint(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
efivar_set(LOADER_GUID, L"LoaderFirmwareType", typestr, FALSE); efivar_set(LOADER_GUID, L"LoaderFirmwareType", typestr, 0);
(void) efivar_set_uint64_le(LOADER_GUID, L"LoaderFeatures", loader_features, FALSE); (void) efivar_set_uint64_le(LOADER_GUID, L"LoaderFeatures", loader_features, 0);
err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image, err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image,
image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
@ -2363,7 +2371,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
/* export the device path this image is started from */ /* export the device path this image is started from */
if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS) if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS)
efivar_set(LOADER_GUID, L"LoaderDevicePartUUID", uuid, FALSE); efivar_set(LOADER_GUID, L"LoaderDevicePartUUID", uuid, 0);
root_dir = LibOpenRoot(loaded_image->DeviceHandle); root_dir = LibOpenRoot(loaded_image->DeviceHandle);
if (!root_dir) { if (!root_dir) {
@ -2383,7 +2391,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
/* the filesystem path to this image, to prevent adding ourselves to the menu */ /* the filesystem path to this image, to prevent adding ourselves to the menu */
loaded_image_path = DevicePathToStr(loaded_image->FilePath); loaded_image_path = DevicePathToStr(loaded_image->FilePath);
efivar_set(LOADER_GUID, L"LoaderImageIdentifier", loaded_image_path, FALSE); efivar_set(LOADER_GUID, L"LoaderImageIdentifier", loaded_image_path, 0);
config_load_defaults(&config, root_dir); config_load_defaults(&config, root_dir);
@ -2481,7 +2489,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
config_entry_bump_counters(entry, root_dir); config_entry_bump_counters(entry, root_dir);
/* Export the selected boot entry to the system */ /* Export the selected boot entry to the system */
(VOID) efivar_set(LOADER_GUID, L"LoaderEntrySelected", entry->id, FALSE); (VOID) efivar_set(LOADER_GUID, L"LoaderEntrySelected", entry->id, 0);
/* Optionally, read a random seed off the ESP and pass it to the OS */ /* Optionally, read a random seed off the ESP and pass it to the OS */
(VOID) process_random_seed(root_dir, config.random_seed_mode); (VOID) process_random_seed(root_dir, config.random_seed_mode);

View File

@ -315,7 +315,7 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) {
} }
/* We are good to go */ /* We are good to go */
err = efivar_set_raw(LOADER_GUID, L"LoaderRandomSeed", for_kernel, size, FALSE); err = efivar_set_raw(LOADER_GUID, L"LoaderRandomSeed", for_kernel, size, 0);
if (EFI_ERROR(err)) { if (EFI_ERROR(err)) {
Print(L"Failed to write random seed to EFI variable: %r\n", err); Print(L"Failed to write random seed to EFI variable: %r\n", err);
return err; return err;

View File

@ -82,14 +82,14 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
/* Export the device path this image is started from, if it's not set yet */ /* Export the device path this image is started from, if it's not set yet */
if (efivar_get_raw(LOADER_GUID, L"LoaderDevicePartUUID", NULL, NULL) != EFI_SUCCESS) if (efivar_get_raw(LOADER_GUID, L"LoaderDevicePartUUID", NULL, NULL) != EFI_SUCCESS)
if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS) if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS)
efivar_set(LOADER_GUID, L"LoaderDevicePartUUID", uuid, FALSE); efivar_set(LOADER_GUID, L"LoaderDevicePartUUID", uuid, 0);
/* if LoaderImageIdentifier is not set, assume the image with this stub was loaded directly from UEFI */ /* if LoaderImageIdentifier is not set, assume the image with this stub was loaded directly from UEFI */
if (efivar_get_raw(LOADER_GUID, L"LoaderImageIdentifier", NULL, NULL) != EFI_SUCCESS) { if (efivar_get_raw(LOADER_GUID, L"LoaderImageIdentifier", NULL, NULL) != EFI_SUCCESS) {
_cleanup_freepool_ CHAR16 *s; _cleanup_freepool_ CHAR16 *s;
s = DevicePathToStr(loaded_image->FilePath); s = DevicePathToStr(loaded_image->FilePath);
efivar_set(LOADER_GUID, L"LoaderImageIdentifier", s, FALSE); efivar_set(LOADER_GUID, L"LoaderImageIdentifier", s, 0);
} }
/* if LoaderFirmwareInfo is not set, let's set it */ /* if LoaderFirmwareInfo is not set, let's set it */
@ -97,7 +97,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
_cleanup_freepool_ CHAR16 *s; _cleanup_freepool_ CHAR16 *s;
s = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); s = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
efivar_set(LOADER_GUID, L"LoaderFirmwareInfo", s, FALSE); efivar_set(LOADER_GUID, L"LoaderFirmwareInfo", s, 0);
} }
/* ditto for LoaderFirmwareType */ /* ditto for LoaderFirmwareType */
@ -105,12 +105,12 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
_cleanup_freepool_ CHAR16 *s; _cleanup_freepool_ CHAR16 *s;
s = PoolPrint(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); s = PoolPrint(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
efivar_set(LOADER_GUID, L"LoaderFirmwareType", s, FALSE); efivar_set(LOADER_GUID, L"LoaderFirmwareType", s, 0);
} }
/* add StubInfo */ /* add StubInfo */
if (efivar_get_raw(LOADER_GUID, L"StubInfo", NULL, NULL) != EFI_SUCCESS) if (efivar_get_raw(LOADER_GUID, L"StubInfo", NULL, NULL) != EFI_SUCCESS)
efivar_set(LOADER_GUID, L"StubInfo", L"systemd-stub " GIT_VERSION, FALSE); efivar_set(LOADER_GUID, L"StubInfo", L"systemd-stub " GIT_VERSION, 0);
if (szs[3] > 0) if (szs[3] > 0)
graphics_splash((UINT8 *)((UINTN)loaded_image->ImageBase + addrs[3]), szs[3], NULL); graphics_splash((UINT8 *)((UINTN)loaded_image->ImageBase + addrs[3]), szs[3], NULL);

View File

@ -75,29 +75,23 @@ EFI_STATUS parse_boolean(const CHAR8 *v, BOOLEAN *b) {
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
} }
EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, const CHAR16 *name, const VOID *buf, UINTN size, BOOLEAN persistent) { EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, const CHAR16 *name, const VOID *buf, UINTN size, UINT32 flags) {
UINT32 flags; flags |= EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
flags = EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
if (persistent)
flags |= EFI_VARIABLE_NON_VOLATILE;
return uefi_call_wrapper(RT->SetVariable, 5, (CHAR16*) name, (EFI_GUID *)vendor, flags, size, (VOID*) buf); return uefi_call_wrapper(RT->SetVariable, 5, (CHAR16*) name, (EFI_GUID *)vendor, flags, size, (VOID*) buf);
} }
EFI_STATUS efivar_set(const EFI_GUID *vendor, const CHAR16 *name, const CHAR16 *value, BOOLEAN persistent) { EFI_STATUS efivar_set(const EFI_GUID *vendor, const CHAR16 *name, const CHAR16 *value, UINT32 flags) {
return efivar_set_raw( return efivar_set_raw(vendor, name, value, value ? (StrLen(value) + 1) * sizeof(CHAR16) : 0, flags);
vendor, name, value, value ? (StrLen(value) + 1) * sizeof(CHAR16) : 0, persistent);
} }
EFI_STATUS efivar_set_uint_string(const EFI_GUID *vendor, CHAR16 *name, UINTN i, BOOLEAN persistent) { EFI_STATUS efivar_set_uint_string(const EFI_GUID *vendor, CHAR16 *name, UINTN i, UINT32 flags) {
CHAR16 str[32]; CHAR16 str[32];
SPrint(str, 32, L"%u", i); SPrint(str, 32, L"%u", i);
return efivar_set(vendor, name, str, persistent); return efivar_set(vendor, name, str, flags);
} }
EFI_STATUS efivar_set_uint32_le(const EFI_GUID *vendor, CHAR16 *name, UINT32 value, BOOLEAN persistent) { EFI_STATUS efivar_set_uint32_le(const EFI_GUID *vendor, CHAR16 *name, UINT32 value, UINT32 flags) {
UINT8 buf[4]; UINT8 buf[4];
buf[0] = (UINT8)(value >> 0U & 0xFF); buf[0] = (UINT8)(value >> 0U & 0xFF);
@ -105,10 +99,10 @@ EFI_STATUS efivar_set_uint32_le(const EFI_GUID *vendor, CHAR16 *name, UINT32 val
buf[2] = (UINT8)(value >> 16U & 0xFF); buf[2] = (UINT8)(value >> 16U & 0xFF);
buf[3] = (UINT8)(value >> 24U & 0xFF); buf[3] = (UINT8)(value >> 24U & 0xFF);
return efivar_set_raw(vendor, name, buf, sizeof(buf), persistent); return efivar_set_raw(vendor, name, buf, sizeof(buf), flags);
} }
EFI_STATUS efivar_set_uint64_le(const EFI_GUID *vendor, CHAR16 *name, UINT64 value, BOOLEAN persistent) { EFI_STATUS efivar_set_uint64_le(const EFI_GUID *vendor, CHAR16 *name, UINT64 value, UINT32 flags) {
UINT8 buf[8]; UINT8 buf[8];
buf[0] = (UINT8)(value >> 0U & 0xFF); buf[0] = (UINT8)(value >> 0U & 0xFF);
@ -120,7 +114,7 @@ EFI_STATUS efivar_set_uint64_le(const EFI_GUID *vendor, CHAR16 *name, UINT64 val
buf[6] = (UINT8)(value >> 48U & 0xFF); buf[6] = (UINT8)(value >> 48U & 0xFF);
buf[7] = (UINT8)(value >> 56U & 0xFF); buf[7] = (UINT8)(value >> 56U & 0xFF);
return efivar_set_raw(vendor, name, buf, sizeof(buf), persistent); return efivar_set_raw(vendor, name, buf, sizeof(buf), flags);
} }
EFI_STATUS efivar_get(const EFI_GUID *vendor, const CHAR16 *name, CHAR16 **value) { EFI_STATUS efivar_get(const EFI_GUID *vendor, const CHAR16 *name, CHAR16 **value) {
@ -248,7 +242,7 @@ VOID efivar_set_time_usec(const EFI_GUID *vendor, CHAR16 *name, UINT64 usec) {
return; return;
SPrint(str, 32, L"%ld", usec); SPrint(str, 32, L"%ld", usec);
efivar_set(vendor, name, str, FALSE); efivar_set(vendor, name, str, 0);
} }
static INTN utf8_to_16(CHAR8 *stra, CHAR16 *c) { static INTN utf8_to_16(CHAR8 *stra, CHAR16 *c) {

View File

@ -21,11 +21,11 @@ UINT64 ticks_read(void);
UINT64 ticks_freq(void); UINT64 ticks_freq(void);
UINT64 time_usec(void); UINT64 time_usec(void);
EFI_STATUS efivar_set(const EFI_GUID *vendor, const CHAR16 *name, const CHAR16 *value, BOOLEAN persistent); EFI_STATUS efivar_set(const EFI_GUID *vendor, const CHAR16 *name, const CHAR16 *value, UINT32 flags);
EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, const CHAR16 *name, const VOID *buf, UINTN size, BOOLEAN persistent); EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, const CHAR16 *name, const VOID *buf, UINTN size, UINT32 flags);
EFI_STATUS efivar_set_uint_string(const EFI_GUID *vendor, CHAR16 *name, UINTN i, BOOLEAN persistent); EFI_STATUS efivar_set_uint_string(const EFI_GUID *vendor, CHAR16 *name, UINTN i, UINT32 flags);
EFI_STATUS efivar_set_uint32_le(const EFI_GUID *vendor, CHAR16 *NAME, UINT32 value, BOOLEAN persistent); EFI_STATUS efivar_set_uint32_le(const EFI_GUID *vendor, CHAR16 *NAME, UINT32 value, UINT32 flags);
EFI_STATUS efivar_set_uint64_le(const EFI_GUID *vendor, CHAR16 *name, UINT64 value, BOOLEAN persistent); EFI_STATUS efivar_set_uint64_le(const EFI_GUID *vendor, CHAR16 *name, UINT64 value, UINT32 flags);
VOID efivar_set_time_usec(const EFI_GUID *vendor, CHAR16 *name, UINT64 usec); VOID efivar_set_time_usec(const EFI_GUID *vendor, CHAR16 *name, UINT64 usec);
EFI_STATUS efivar_get(const EFI_GUID *vendor, const CHAR16 *name, CHAR16 **value); EFI_STATUS efivar_get(const EFI_GUID *vendor, const CHAR16 *name, CHAR16 **value);

View File

@ -417,7 +417,7 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
"%sDelegate: %s\n" "%sDelegate: %s\n"
"%sManagedOOMSwap: %s\n" "%sManagedOOMSwap: %s\n"
"%sManagedOOMMemoryPressure: %s\n" "%sManagedOOMMemoryPressure: %s\n"
"%sManagedOOMMemoryPressureLimitPercent: %d%%\n", "%sManagedOOMMemoryPressureLimit: %" PRIu32 ".%02" PRIu32 "%%\n",
prefix, yes_no(c->cpu_accounting), prefix, yes_no(c->cpu_accounting),
prefix, yes_no(c->io_accounting), prefix, yes_no(c->io_accounting),
prefix, yes_no(c->blockio_accounting), prefix, yes_no(c->blockio_accounting),
@ -450,7 +450,7 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
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_swap),
prefix, managed_oom_mode_to_string(c->moom_mem_pressure), prefix, managed_oom_mode_to_string(c->moom_mem_pressure),
prefix, c->moom_mem_pressure_limit); prefix, c->moom_mem_pressure_limit_permyriad / 100, c->moom_mem_pressure_limit_permyriad % 100);
if (c->delegate) { if (c->delegate) {
_cleanup_free_ char *t = NULL; _cleanup_free_ char *t = NULL;
@ -1057,6 +1057,23 @@ static int cgroup_apply_devices(Unit *u) {
return r; return r;
} }
static void set_io_weight(Unit *u, const char *controller, uint64_t weight) {
char buf[8+DECIMAL_STR_MAX(uint64_t)+1];
const char *p;
p = strjoina(controller, ".weight");
xsprintf(buf, "default %" PRIu64 "\n", weight);
(void) set_attribute_and_warn(u, controller, p, buf);
/* FIXME: drop this when distro kernels properly support BFQ through "io.weight"
* See also: https://github.com/systemd/systemd/pull/13335 and
* https://github.com/torvalds/linux/commit/65752aef0a407e1ef17ec78a7fc31ba4e0b360f9.
* The range is 1..1000 apparently. */
p = strjoina(controller, ".bfq.weight");
xsprintf(buf, "%" PRIu64 "\n", (weight + 9) / 10);
(void) set_attribute_and_warn(u, controller, p, buf);
}
static void cgroup_context_apply( static void cgroup_context_apply(
Unit *u, Unit *u,
CGroupMask apply_mask, CGroupMask apply_mask,
@ -1143,7 +1160,6 @@ static void cgroup_context_apply(
* controller), and in case of containers we want to leave control of these attributes to the container manager * controller), and in case of containers we want to leave control of these attributes to the container manager
* (and we couldn't access that stuff anyway, even if we tried if proper delegation is used). */ * (and we couldn't access that stuff anyway, even if we tried if proper delegation is used). */
if ((apply_mask & CGROUP_MASK_IO) && !is_local_root) { if ((apply_mask & CGROUP_MASK_IO) && !is_local_root) {
char buf[8+DECIMAL_STR_MAX(uint64_t)+1];
bool has_io, has_blockio; bool has_io, has_blockio;
uint64_t weight; uint64_t weight;
@ -1163,13 +1179,7 @@ static void cgroup_context_apply(
} else } else
weight = CGROUP_WEIGHT_DEFAULT; weight = CGROUP_WEIGHT_DEFAULT;
xsprintf(buf, "default %" PRIu64 "\n", weight); set_io_weight(u, "io", weight);
(void) set_attribute_and_warn(u, "io", "io.weight", buf);
/* FIXME: drop this when distro kernels properly support BFQ through "io.weight"
* See also: https://github.com/systemd/systemd/pull/13335 */
xsprintf(buf, "%" PRIu64 "\n", weight);
(void) set_attribute_and_warn(u, "io", "io.bfq.weight", buf);
if (has_io) { if (has_io) {
CGroupIODeviceLatency *latency; CGroupIODeviceLatency *latency;
@ -1225,7 +1235,6 @@ static void cgroup_context_apply(
/* Applying a 'weight' never makes sense for the host root cgroup, and for containers this should be /* Applying a 'weight' never makes sense for the host root cgroup, and for containers this should be
* left to our container manager, too. */ * left to our container manager, too. */
if (!is_local_root) { if (!is_local_root) {
char buf[DECIMAL_STR_MAX(uint64_t)+1];
uint64_t weight; uint64_t weight;
if (has_io) { if (has_io) {
@ -1241,13 +1250,7 @@ static void cgroup_context_apply(
else else
weight = CGROUP_BLKIO_WEIGHT_DEFAULT; weight = CGROUP_BLKIO_WEIGHT_DEFAULT;
xsprintf(buf, "%" PRIu64 "\n", weight); set_io_weight(u, "blkio", weight);
(void) set_attribute_and_warn(u, "blkio", "blkio.weight", buf);
/* FIXME: drop this when distro kernels properly support BFQ through "blkio.weight"
* See also: https://github.com/systemd/systemd/pull/13335 */
xsprintf(buf, "%" PRIu64 "\n", weight);
(void) set_attribute_and_warn(u, "blkio", "blkio.bfq.weight", buf);
if (has_io) { if (has_io) {
CGroupIODeviceWeight *w; CGroupIODeviceWeight *w;

View File

@ -163,7 +163,7 @@ struct CGroupContext {
/* Settings for systemd-oomd */ /* Settings for systemd-oomd */
ManagedOOMMode moom_swap; ManagedOOMMode moom_swap;
ManagedOOMMode moom_mem_pressure; ManagedOOMMode moom_mem_pressure;
int moom_mem_pressure_limit; uint32_t moom_mem_pressure_limit_permyriad;
}; };
/* Used when querying IP accounting data */ /* Used when querying IP accounting data */

View File

@ -83,7 +83,7 @@ static int build_managed_oom_json_array_element(Unit *u, const char *property, J
JSON_BUILD_PAIR("mode", JSON_BUILD_STRING(mode)), JSON_BUILD_PAIR("mode", JSON_BUILD_STRING(mode)),
JSON_BUILD_PAIR("path", JSON_BUILD_STRING(u->cgroup_path)), JSON_BUILD_PAIR("path", JSON_BUILD_STRING(u->cgroup_path)),
JSON_BUILD_PAIR("property", JSON_BUILD_STRING(property)), JSON_BUILD_PAIR("property", JSON_BUILD_STRING(property)),
JSON_BUILD_PAIR_CONDITION(use_limit, "limit", JSON_BUILD_UNSIGNED(c->moom_mem_pressure_limit)))); JSON_BUILD_PAIR_CONDITION(use_limit, "limit", JSON_BUILD_UNSIGNED(c->moom_mem_pressure_limit_permyriad))));
} }
int manager_varlink_send_managed_oom_update(Unit *u) { int manager_varlink_send_managed_oom_update(Unit *u) {

View File

@ -394,7 +394,7 @@ const sd_bus_vtable bus_cgroup_vtable[] = {
SD_BUS_PROPERTY("DisableControllers", "as", property_get_cgroup_mask, offsetof(CGroupContext, disable_controllers), 0), SD_BUS_PROPERTY("DisableControllers", "as", property_get_cgroup_mask, offsetof(CGroupContext, disable_controllers), 0),
SD_BUS_PROPERTY("ManagedOOMSwap", "s", property_get_managed_oom_mode, offsetof(CGroupContext, moom_swap), 0), SD_BUS_PROPERTY("ManagedOOMSwap", "s", property_get_managed_oom_mode, offsetof(CGroupContext, moom_swap), 0),
SD_BUS_PROPERTY("ManagedOOMMemoryPressure", "s", property_get_managed_oom_mode, offsetof(CGroupContext, moom_mem_pressure), 0), SD_BUS_PROPERTY("ManagedOOMMemoryPressure", "s", property_get_managed_oom_mode, offsetof(CGroupContext, moom_mem_pressure), 0),
SD_BUS_PROPERTY("ManagedOOMMemoryPressureLimitPercent", "s", bus_property_get_percent, offsetof(CGroupContext, moom_mem_pressure_limit), 0), SD_BUS_PROPERTY("ManagedOOMMemoryPressureLimitPermyriad", "u", NULL, offsetof(CGroupContext, moom_mem_pressure_limit_permyriad), 0),
SD_BUS_VTABLE_END SD_BUS_VTABLE_END
}; };
@ -1696,14 +1696,24 @@ int bus_cgroup_set_property(
return 1; return 1;
} }
if (streq(name, "ManagedOOMMemoryPressureLimitPercent")) { if (streq(name, "ManagedOOMMemoryPressureLimitPermyriad")) {
uint32_t v;
if (!UNIT_VTABLE(u)->can_set_managed_oom) if (!UNIT_VTABLE(u)->can_set_managed_oom)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot set %s for this unit type", name); return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot set %s for this unit type", name);
r = bus_set_transient_percent(u, name, &c->moom_mem_pressure_limit, message, flags, error); r = sd_bus_message_read(message, "u", &v);
if (r < 0) if (r < 0)
return r; return r;
if (v > 10000)
return -ERANGE;
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->moom_mem_pressure_limit_permyriad = v;
unit_write_settingf(u, flags, name, "ManagedOOMMemoryPressureLimit=%" PRIu32 ".%02" PRIu32 "%%", v / 100, v % 100);
}
if (c->moom_mem_pressure == MANAGED_OOM_KILL) if (c->moom_mem_pressure == MANAGED_OOM_KILL)
(void) manager_varlink_send_managed_oom_update(u); (void) manager_varlink_send_managed_oom_update(u);

View File

@ -93,35 +93,6 @@ int bus_set_transient_bool(
return 1; return 1;
} }
int bus_set_transient_percent(
Unit *u,
const char *name,
int *p,
sd_bus_message *message,
UnitWriteFlags flags,
sd_bus_error *error) {
const char *v;
int r;
assert(p);
r = sd_bus_message_read(message, "s", &v);
if (r < 0)
return r;
r = parse_percent(v);
if (r < 0)
return r;
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
*p = r;
unit_write_settingf(u, flags, name, "%s=%d%%", name, r);
}
return 1;
}
int bus_set_transient_usec_internal( int bus_set_transient_usec_internal(
Unit *u, Unit *u,
const char *name, const char *name,

View File

@ -241,7 +241,6 @@ int bus_set_transient_user_relaxed(Unit *u, const char *name, char **p, sd_bus_m
int bus_set_transient_path(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); int bus_set_transient_path(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
int bus_set_transient_string(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); int bus_set_transient_string(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
int bus_set_transient_bool(Unit *u, const char *name, bool *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); int bus_set_transient_bool(Unit *u, const char *name, bool *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
int bus_set_transient_percent(Unit *u, const char *name, int *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
int bus_set_transient_usec_internal(Unit *u, const char *name, usec_t *p, bool fix_0, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); int bus_set_transient_usec_internal(Unit *u, const char *name, usec_t *p, bool fix_0, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
static inline int bus_set_transient_usec(Unit *u, const char *name, usec_t *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error) { static inline int bus_set_transient_usec(Unit *u, const char *name, usec_t *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error) {
return bus_set_transient_usec_internal(u, name, p, false, message, flags, error); return bus_set_transient_usec_internal(u, name, p, false, message, flags, error);

View File

@ -229,7 +229,7 @@ $1.IPIngressFilterPath, config_parse_ip_filter_bpf_progs,
$1.IPEgressFilterPath, config_parse_ip_filter_bpf_progs, 0, offsetof($1, cgroup_context.ip_filters_egress) $1.IPEgressFilterPath, config_parse_ip_filter_bpf_progs, 0, offsetof($1, cgroup_context.ip_filters_egress)
$1.ManagedOOMSwap, config_parse_managed_oom_mode, 0, offsetof($1, cgroup_context.moom_swap) $1.ManagedOOMSwap, config_parse_managed_oom_mode, 0, offsetof($1, cgroup_context.moom_swap)
$1.ManagedOOMMemoryPressure, config_parse_managed_oom_mode, 0, offsetof($1, cgroup_context.moom_mem_pressure) $1.ManagedOOMMemoryPressure, config_parse_managed_oom_mode, 0, offsetof($1, cgroup_context.moom_mem_pressure)
$1.ManagedOOMMemoryPressureLimitPercent, config_parse_managed_oom_mem_pressure_limit, 0, offsetof($1, cgroup_context.moom_mem_pressure_limit) $1.ManagedOOMMemoryPressureLimit, config_parse_managed_oom_mem_pressure_limit, 0, offsetof($1, cgroup_context.moom_mem_pressure_limit_permyriad)
$1.NetClass, config_parse_warn_compat, DISABLED_LEGACY, 0' $1.NetClass, config_parse_warn_compat, DISABLED_LEGACY, 0'
)m4_dnl )m4_dnl
Unit.Description, config_parse_unit_string_printf, 0, offsetof(Unit, description) Unit.Description, config_parse_unit_string_printf, 0, offsetof(Unit, description)

View File

@ -3875,7 +3875,7 @@ int config_parse_managed_oom_mem_pressure_limit(
const char *rvalue, const char *rvalue,
void *data, void *data,
void *userdata) { void *userdata) {
int *limit = data; uint32_t *limit = data;
UnitType t; UnitType t;
int r; int r;
@ -3890,9 +3890,9 @@ int config_parse_managed_oom_mem_pressure_limit(
return 0; return 0;
} }
r = parse_percent(rvalue); r = parse_permyriad(rvalue);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse limit percent value, ignoring: %s", rvalue); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse memory pressure limit value, ignoring: %s", rvalue);
return 0; return 0;
} }

View File

@ -100,10 +100,10 @@ static int process_managed_oom_reply(
limit = m->default_mem_pressure_limit; limit = m->default_mem_pressure_limit;
if (streq(reply.property, "ManagedOOMMemoryPressure")) { if (streq(reply.property, "ManagedOOMMemoryPressure")) {
if (reply.limit > 100) if (reply.limit > 10000)
continue; continue;
else if (reply.limit != 0) { else if (reply.limit != 0) {
ret = store_loadavg_fixed_point((unsigned long) reply.limit, 0, &limit); ret = store_loadavg_fixed_point((unsigned long) reply.limit / 100, (unsigned long) reply.limit % 100, &limit);
if (ret < 0) if (ret < 0)
continue; continue;
} }
@ -478,8 +478,8 @@ static int manager_connect_bus(Manager *m) {
return 0; return 0;
} }
int manager_start(Manager *m, bool dry_run, int swap_used_limit, int mem_pressure_limit, usec_t mem_pressure_usec) { int manager_start(Manager *m, bool dry_run, int swap_used_limit, int mem_pressure_limit_permyriad, usec_t mem_pressure_usec) {
unsigned long l; unsigned long l, f;
int r; int r;
assert(m); assert(m);
@ -489,8 +489,16 @@ int manager_start(Manager *m, bool dry_run, int swap_used_limit, int mem_pressur
m->swap_used_limit = swap_used_limit != -1 ? swap_used_limit : DEFAULT_SWAP_USED_LIMIT; m->swap_used_limit = swap_used_limit != -1 ? swap_used_limit : DEFAULT_SWAP_USED_LIMIT;
assert(m->swap_used_limit <= 100); assert(m->swap_used_limit <= 100);
l = mem_pressure_limit != -1 ? mem_pressure_limit : DEFAULT_MEM_PRESSURE_LIMIT; if (mem_pressure_limit_permyriad != -1) {
r = store_loadavg_fixed_point(l, 0, &m->default_mem_pressure_limit); assert(mem_pressure_limit_permyriad <= 10000);
l = mem_pressure_limit_permyriad / 100;
f = mem_pressure_limit_permyriad % 100;
} else {
l = DEFAULT_MEM_PRESSURE_LIMIT_PERCENT;
f = 0;
}
r = store_loadavg_fixed_point(l, f, &m->default_mem_pressure_limit);
if (r < 0) if (r < 0)
return r; return r;
@ -530,12 +538,12 @@ int manager_get_dump_string(Manager *m, char **ret) {
fprintf(f, fprintf(f,
"Dry Run: %s\n" "Dry Run: %s\n"
"Swap Used Limit: %u%%\n" "Swap Used Limit: %u%%\n"
"Default Memory Pressure Limit: %lu%%\n" "Default Memory Pressure Limit: %lu.%02lu%%\n"
"Default Memory Pressure Duration: %s\n" "Default Memory Pressure Duration: %s\n"
"System Context:\n", "System Context:\n",
yes_no(m->dry_run), yes_no(m->dry_run),
m->swap_used_limit, m->swap_used_limit,
LOAD_INT(m->default_mem_pressure_limit), LOAD_INT(m->default_mem_pressure_limit), LOAD_FRAC(m->default_mem_pressure_limit),
format_timespan(buf, sizeof(buf), m->default_mem_pressure_duration_usec, USEC_PER_SEC)); format_timespan(buf, sizeof(buf), m->default_mem_pressure_duration_usec, USEC_PER_SEC));
oomd_dump_system_context(&m->system_context, f, "\t"); oomd_dump_system_context(&m->system_context, f, "\t");

View File

@ -17,7 +17,7 @@
* Generally 60 or higher might be acceptable for something like system.slice with no memory.high set; processes in * Generally 60 or higher might be acceptable for something like system.slice with no memory.high set; processes in
* system.slice are assumed to be less latency sensitive. */ * system.slice are assumed to be less latency sensitive. */
#define DEFAULT_MEM_PRESSURE_DURATION_USEC (30 * USEC_PER_SEC) #define DEFAULT_MEM_PRESSURE_DURATION_USEC (30 * USEC_PER_SEC)
#define DEFAULT_MEM_PRESSURE_LIMIT 60 #define DEFAULT_MEM_PRESSURE_LIMIT_PERCENT 60
#define DEFAULT_SWAP_USED_LIMIT 90 #define DEFAULT_SWAP_USED_LIMIT 90
#define RECLAIM_DURATION_USEC (30 * USEC_PER_SEC) #define RECLAIM_DURATION_USEC (30 * USEC_PER_SEC)
@ -56,7 +56,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
int manager_new(Manager **ret); int manager_new(Manager **ret);
int manager_start(Manager *m, bool dry_run, int swap_used_limit, int mem_pressure_limit, usec_t mem_pressure_usec); int manager_start(Manager *m, bool dry_run, int swap_used_limit, int mem_pressure_limit_permyriad, usec_t mem_pressure_usec);
int manager_get_dump_string(Manager *m, char **ret); int manager_get_dump_string(Manager *m, char **ret);

View File

@ -415,11 +415,11 @@ void oomd_dump_memory_pressure_cgroup_context(const OomdCGroupContext *ctx, FILE
fprintf(f, fprintf(f,
"%sPath: %s\n" "%sPath: %s\n"
"%s\tMemory Pressure Limit: %lu%%\n" "%s\tMemory Pressure Limit: %lu.%02lu%%\n"
"%s\tPressure: Avg10: %lu.%02lu Avg60: %lu.%02lu Avg300: %lu.%02lu Total: %s\n" "%s\tPressure: Avg10: %lu.%02lu Avg60: %lu.%02lu Avg300: %lu.%02lu Total: %s\n"
"%s\tCurrent Memory Usage: %s\n", "%s\tCurrent Memory Usage: %s\n",
strempty(prefix), ctx->path, strempty(prefix), ctx->path,
strempty(prefix), LOAD_INT(ctx->mem_pressure_limit), strempty(prefix), LOAD_INT(ctx->mem_pressure_limit), LOAD_FRAC(ctx->mem_pressure_limit),
strempty(prefix), strempty(prefix),
LOAD_INT(ctx->memory_pressure.avg10), LOAD_FRAC(ctx->memory_pressure.avg10), LOAD_INT(ctx->memory_pressure.avg10), LOAD_FRAC(ctx->memory_pressure.avg10),
LOAD_INT(ctx->memory_pressure.avg60), LOAD_FRAC(ctx->memory_pressure.avg60), LOAD_INT(ctx->memory_pressure.avg60), LOAD_FRAC(ctx->memory_pressure.avg60),

View File

@ -18,13 +18,13 @@
static bool arg_dry_run = false; static bool arg_dry_run = false;
static int arg_swap_used_limit = -1; static int arg_swap_used_limit = -1;
static int arg_mem_pressure_limit = -1; static int arg_mem_pressure_limit_permyriad = -1;
static usec_t arg_mem_pressure_usec = 0; static usec_t arg_mem_pressure_usec = 0;
static int parse_config(void) { static int parse_config(void) {
static const ConfigTableItem items[] = { static const ConfigTableItem items[] = {
{ "OOM", "SwapUsedLimitPercent", config_parse_percent, 0, &arg_swap_used_limit }, { "OOM", "SwapUsedLimitPercent", config_parse_percent, 0, &arg_swap_used_limit },
{ "OOM", "DefaultMemoryPressureLimitPercent", config_parse_percent, 0, &arg_mem_pressure_limit }, { "OOM", "DefaultMemoryPressureLimit", config_parse_permyriad, 0, &arg_mem_pressure_limit_permyriad },
{ "OOM", "DefaultMemoryPressureDurationSec", config_parse_sec, 0, &arg_mem_pressure_usec }, { "OOM", "DefaultMemoryPressureDurationSec", config_parse_sec, 0, &arg_mem_pressure_usec },
{} {}
}; };
@ -159,7 +159,7 @@ static int run(int argc, char *argv[]) {
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to create manager: %m"); return log_error_errno(r, "Failed to create manager: %m");
r = manager_start(m, arg_dry_run, arg_swap_used_limit, arg_mem_pressure_limit, arg_mem_pressure_usec); r = manager_start(m, arg_dry_run, arg_swap_used_limit, arg_mem_pressure_limit_permyriad, arg_mem_pressure_usec);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to start up daemon: %m"); return log_error_errno(r, "Failed to start up daemon: %m");

View File

@ -13,5 +13,5 @@
[OOM] [OOM]
#SwapUsedLimitPercent=90% #SwapUsedLimitPercent=90%
#DefaultMemoryPressureLimitPercent=60% #DefaultMemoryPressureLimit=60%
#DefaultMemoryPressureDurationSec=30s #DefaultMemoryPressureDurationSec=30s

View File

@ -55,23 +55,6 @@ int bus_property_get_id128(
return sd_bus_message_append_array(reply, 'y', id->bytes, 16); return sd_bus_message_append_array(reply, 'y', id->bytes, 16);
} }
int bus_property_get_percent(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
char pstr[DECIMAL_STR_MAX(int) + 2];
int p = *(int*) userdata;
xsprintf(pstr, "%d%%", p);
return sd_bus_message_append_basic(reply, 's', pstr);
}
#if __SIZEOF_SIZE_T__ != 8 #if __SIZEOF_SIZE_T__ != 8
int bus_property_get_size( int bus_property_get_size(
sd_bus *bus, sd_bus *bus,

View File

@ -8,7 +8,6 @@
int bus_property_get_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); int bus_property_get_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
int bus_property_set_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error); int bus_property_set_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error);
int bus_property_get_id128(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); int bus_property_get_id128(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
int bus_property_get_percent(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
#define bus_property_get_usec ((sd_bus_property_get_t) NULL) #define bus_property_get_usec ((sd_bus_property_get_t) NULL)
#define bus_property_set_usec ((sd_bus_property_set_t) NULL) #define bus_property_set_usec ((sd_bus_property_set_t) NULL)

View File

@ -435,10 +435,25 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons
if (STR_IN_SET(field, "DevicePolicy", if (STR_IN_SET(field, "DevicePolicy",
"Slice", "Slice",
"ManagedOOMSwap", "ManagedOOMSwap",
"ManagedOOMMemoryPressure", "ManagedOOMMemoryPressure"))
"ManagedOOMMemoryPressureLimitPercent"))
return bus_append_string(m, field, eq); return bus_append_string(m, field, eq);
if (STR_IN_SET(field, "ManagedOOMMemoryPressureLimit")) {
char *n;
r = parse_permyriad(eq);
if (r < 0)
return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
n = strjoina(field, "Permyriad");
r = sd_bus_message_append(m, "(sv)", n, "u", (uint32_t) r);
if (r < 0)
return bus_log_create_error(r);
return 1;
}
if (STR_IN_SET(field, "CPUAccounting", if (STR_IN_SET(field, "CPUAccounting",
"MemoryAccounting", "MemoryAccounting",
"IOAccounting", "IOAccounting",

View File

@ -1356,3 +1356,4 @@ int config_parse_hwaddrs(
} }
DEFINE_CONFIG_PARSE(config_parse_percent, parse_percent, "Failed to parse percent value"); DEFINE_CONFIG_PARSE(config_parse_percent, parse_percent, "Failed to parse percent value");
DEFINE_CONFIG_PARSE(config_parse_permyriad, parse_permyriad, "Failed to parse permyriad value");

View File

@ -150,6 +150,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_vlanprotocol);
CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr); CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr);
CONFIG_PARSER_PROTOTYPE(config_parse_hwaddrs); CONFIG_PARSER_PROTOTYPE(config_parse_hwaddrs);
CONFIG_PARSER_PROTOTYPE(config_parse_percent); CONFIG_PARSER_PROTOTYPE(config_parse_percent);
CONFIG_PARSER_PROTOTYPE(config_parse_permyriad);
typedef enum Disabled { typedef enum Disabled {
DISABLED_CONFIGURATION, DISABLED_CONFIGURATION,

View File

@ -790,6 +790,72 @@ static void test_parse_permille_unbounded(void) {
assert_se(parse_permille_unbounded("429496729.6%") == -ERANGE); assert_se(parse_permille_unbounded("429496729.6%") == -ERANGE);
} }
static void test_parse_permyriad(void) {
assert_se(parse_permyriad("") == -EINVAL);
assert_se(parse_permyriad("foo") == -EINVAL);
assert_se(parse_permyriad("0") == -EINVAL);
assert_se(parse_permyriad("50") == -EINVAL);
assert_se(parse_permyriad("100") == -EINVAL);
assert_se(parse_permyriad("-1") == -EINVAL);
assert_se(parse_permyriad("0‱") == 0);
assert_se(parse_permyriad("555‱") == 555);
assert_se(parse_permyriad("1000‱") == 1000);
assert_se(parse_permyriad("-7‱") == -ERANGE);
assert_se(parse_permyriad("10007‱") == -ERANGE);
assert_se(parse_permyriad("") == -EINVAL);
assert_se(parse_permyriad("‱‱") == -EINVAL);
assert_se(parse_permyriad("‱1") == -EINVAL);
assert_se(parse_permyriad("1‱‱") == -EINVAL);
assert_se(parse_permyriad("3.2‱") == -EINVAL);
assert_se(parse_permyriad("0‰") == 0);
assert_se(parse_permyriad("555.5‰") == 5555);
assert_se(parse_permyriad("1000.0‰") == 10000);
assert_se(parse_permyriad("-7‰") == -ERANGE);
assert_se(parse_permyriad("1007‰") == -ERANGE);
assert_se(parse_permyriad("") == -EINVAL);
assert_se(parse_permyriad("‰‰") == -EINVAL);
assert_se(parse_permyriad("‰1") == -EINVAL);
assert_se(parse_permyriad("1‰‰") == -EINVAL);
assert_se(parse_permyriad("3.22‰") == -EINVAL);
assert_se(parse_permyriad("0%") == 0);
assert_se(parse_permyriad("55%") == 5500);
assert_se(parse_permyriad("55.53%") == 5553);
assert_se(parse_permyriad("100%") == 10000);
assert_se(parse_permyriad("-7%") == -ERANGE);
assert_se(parse_permyriad("107%") == -ERANGE);
assert_se(parse_permyriad("%") == -EINVAL);
assert_se(parse_permyriad("%%") == -EINVAL);
assert_se(parse_permyriad("%1") == -EINVAL);
assert_se(parse_permyriad("1%%") == -EINVAL);
assert_se(parse_permyriad("3.212%") == -EINVAL);
}
static void test_parse_permyriad_unbounded(void) {
assert_se(parse_permyriad_unbounded("1001‱") == 1001);
assert_se(parse_permyriad_unbounded("4000‱") == 4000);
assert_se(parse_permyriad_unbounded("2147483647‱") == 2147483647);
assert_se(parse_permyriad_unbounded("2147483648‱") == -ERANGE);
assert_se(parse_permyriad_unbounded("4294967295‱") == -ERANGE);
assert_se(parse_permyriad_unbounded("4294967296‱") == -ERANGE);
assert_se(parse_permyriad_unbounded("101‰") == 1010);
assert_se(parse_permyriad_unbounded("400‰") == 4000);
assert_se(parse_permyriad_unbounded("214748364.7‰") == 2147483647);
assert_se(parse_permyriad_unbounded("214748364.8‰") == -ERANGE);
assert_se(parse_permyriad_unbounded("429496729.5‰") == -ERANGE);
assert_se(parse_permyriad_unbounded("429496729.6‰") == -ERANGE);
assert_se(parse_permyriad_unbounded("99%") == 9900);
assert_se(parse_permyriad_unbounded("40%") == 4000);
assert_se(parse_permyriad_unbounded("21474836.47%") == 2147483647);
assert_se(parse_permyriad_unbounded("21474836.48%") == -ERANGE);
assert_se(parse_permyriad_unbounded("42949672.95%") == -ERANGE);
assert_se(parse_permyriad_unbounded("42949672.96%") == -ERANGE);
}
static void test_parse_nice(void) { static void test_parse_nice(void) {
int n; int n;
@ -987,6 +1053,8 @@ int main(int argc, char *argv[]) {
test_parse_percent_unbounded(); test_parse_percent_unbounded();
test_parse_permille(); test_parse_permille();
test_parse_permille_unbounded(); test_parse_permille_unbounded();
test_parse_permyriad();
test_parse_permyriad_unbounded();
test_parse_nice(); test_parse_nice();
test_parse_dev(); test_parse_dev();
test_parse_errno(); test_parse_errno();

View File

@ -13,7 +13,7 @@ static void test_translate_name(void) {
_cleanup_free_ char *t; _cleanup_free_ char *t;
assert_se(t = xdg_autostart_service_translate_name("a-b.blub.desktop")); assert_se(t = xdg_autostart_service_translate_name("a-b.blub.desktop"));
assert_se(streq(t, "app-a\\x2db.blub-autostart.service")); assert_se(streq(t, "app-a\\x2db.blub@autostart.service"));
} }
static void test_xdg_format_exec_start_one(const char *exec, const char *expected) { static void test_xdg_format_exec_start_one(const char *exec, const char *expected) {

View File

@ -58,7 +58,7 @@ char *xdg_autostart_service_translate_name(const char *name) {
if (!escaped) if (!escaped)
return NULL; return NULL;
return strjoin("app-", escaped, "-autostart.service"); return strjoin("app-", escaped, "@autostart.service");
} }
static int xdg_config_parse_bool( static int xdg_config_parse_bool(

View File

@ -7,4 +7,4 @@ MemoryAccounting=true
IOAccounting=true IOAccounting=true
TasksAccounting=true TasksAccounting=true
ManagedOOMMemoryPressure=kill ManagedOOMMemoryPressure=kill
ManagedOOMMemoryPressureLimitPercent=1% ManagedOOMMemoryPressureLimit=1%

View File

@ -20,7 +20,7 @@ systemctl start testsuite-56-testbloat.service
# Verify systemd-oomd is monitoring the expected units # Verify systemd-oomd is monitoring the expected units
oomctl | grep "/testsuite-56-workload.slice" oomctl | grep "/testsuite-56-workload.slice"
oomctl | grep "1%" oomctl | grep "1.00%"
oomctl | grep "Default Memory Pressure Duration: 5s" oomctl | grep "Default Memory Pressure Duration: 5s"
# systemd-oomd watches for elevated pressure for 30 seconds before acting. # systemd-oomd watches for elevated pressure for 30 seconds before acting.