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

Compare commits

...

24 Commits

Author SHA1 Message Date
Ansgar Burchardt
b9b4038831 NEWS: fix typo: as → at 2021-02-14 00:46:40 +09:00
Alan Perry
8db704b28b no blkid for mmcblk[0-9]boot[0-9]
Don't run blkid on mmcblk[0-9]boot[0-9] devices because they contain
bootloaders or boot parameters, and not partitions or file systems.
2021-02-13 10:38:29 +01:00
Zbigniew Jędrzejewski-Szmek
b3c57df0f5
Merge pull request #18401 from anitazha/oomdxattr
oomd: implement avoid/omit support for cgroups
2021-02-13 10:00:31 +01:00
Nick
7253850abf Added Trekstor Yourbook C11B to 60-sensor.hwdb
Added the Trekstor Yourbook C11B which is equivalent to Trekstor Primebook C11B.
2021-02-13 17:47:25 +09:00
Lennart Poettering
3ec2f7f2e3 udev: make net_setup_link builtin quiet when link vanishes while we operate on it
Fixes: #16175
2021-02-13 17:46:56 +09:00
Lennart Poettering
6b10a2e030 core: slightly improve error message on load errors
Let's be a bit more helpful when refusing jobs on units that failed to
load properly. We already have explicit D-Bus errors for the error
conditions that are common and expected (such as "not found"), but for
the rest we so far generate a fairly cryptic message.

Let's try to be friendlier towards users and suggest what to do on such
errors.

Fixes: #16487
2021-02-13 17:46:39 +09:00
Yu Watanabe
9ae4f96056
Merge pull request #18555 from yuwata/network-address-set-flag-on-remove
network: address: also set IFA_FLAGS on remove
2021-02-13 17:44:58 +09:00
Yu Watanabe
b2af6d66fb
Merge pull request #18455 from yuwata/network-change-link-state-only-when-new-address-or-route-will-be-assigned
network: change link state only when new address or route will be assigned
2021-02-13 17:43:27 +09:00
Anita Zhang
d8a4d64bc3 man: document ManagedOOMPreference= 2021-02-12 12:46:22 -08:00
Anita Zhang
4e806bfa9f oom: add unit file settings for oomd avoid/omit xattrs 2021-02-12 12:45:36 -08:00
Yu Watanabe
4a70450104 test-network: merge test_address_static and test_address_preferred_lifetime_zero_ipv6 2021-02-12 23:09:21 +09:00
Yu Watanabe
53ae4762ef network: address: do not set IFA_F_PERMANENT flag
The flag is automatically set by kernel when the valid lifetime is
infinite. Note that the flag in netlink message for IPv4 address is
ignored. See set_ifa_lifetime() in kernel's net/ipv4/devinet.c.
But the flag is honored for IPv6 address. And if the flag is set with
finite valid lifetime, the address will not removed automatically by
the kernel.
2021-02-12 23:09:21 +09:00
Yu Watanabe
a8481354f0 network: address: also set IFA_FLAGS on remove
If an address is assigned with IFA_F_MANAGETEMPADDR, then the flag must
be also set on remove. Otherwise, temporary addresses will not be
removed. See also inet6_rtm_deladdr() in kernel's net/ipv6/addrconf.c.

Fixes #13218.
2021-02-12 23:09:21 +09:00
Yu Watanabe
111ce98419 network: dhcp6: change link state into "configuring" only when a new address or route will be assigned 2021-02-12 22:44:05 +09:00
Yu Watanabe
24b445c2ce network: ndisc: change link state into "configuring" only when a new address or route will be assigned 2021-02-12 22:44:05 +09:00
Yu Watanabe
b54aed29c6 network: dhcp6: fix condtion check 2021-02-12 22:43:39 +09:00
Yu Watanabe
0ef9f3c76f network: set return value at the end of the function
The later netlink_call_async() call may fail. We should not touch the
return value when the function failed.
2021-02-12 22:43:10 +09:00
Yu Watanabe
d9eee312a7 network: make address_configure() or friends return 1 when the address is new 2021-02-12 22:43:10 +09:00
Anita Zhang
59331b8e29 oom: implement avoid/omit xattr support
There may be situations where a cgroup should be protected from killing
or deprioritized as a candidate. In FB oomd xattrs are used to bias oomd
away from supervisor cgroups and towards worker cgroups in container
tasks. On desktops this can be used to protect important units with
unpredictable resource consumption.

The patch allows systemd-oomd to understand 2 xattrs:
"user.oomd_avoid" and "user.oomd_omit". If systemd-oomd sees these
xattrs set to 1 on a candidate cgroup (i.e. while attempting to kill something)
AND the cgroup is owned by root, it will either deprioritize the cgroup as
a candidate (avoid) or remove it completely as a candidate (omit).

Usage is restricted to root owned cgroups to prevent situations where an
unprivileged user can set their own cgroups lower in the kill priority than
another user's (and prevent them from omitting their units from
systemd-oomd killing).
2021-02-09 02:27:40 -08:00
Anita Zhang
242d75bdaa cgroup-util: add ManagedOOMPreference enum to use between pid1 and oomd 2021-02-09 02:27:37 -08:00
Anita Zhang
74f834e9e2 oom: skip over cgroups with no memory usage 2021-02-09 01:30:05 -08:00
Anita Zhang
1f76411bd6 oom: sort by pgscan and memory usage
If 2 candidates have the same pgscan, prioritize the one with the larger
memory usage.
2021-02-09 01:29:57 -08:00
Anita Zhang
df7f3eab52 oom: wrap reply.path with empty_to_root 2021-02-09 01:23:58 -08:00
Anita Zhang
e303833355 oom: shorten xattr name 2021-02-09 01:23:58 -08:00
37 changed files with 515 additions and 183 deletions

2
NEWS
View File

@ -49,7 +49,7 @@ CHANGES WITH 248:
security tokens to LUKS volumes, list and destroy them. See
https://www.freedesktop.org/software/systemd/man/systemd-cryptenroll.html.
* The manager may be configured as compile time to use fexecve instead
* The manager may be configured at compile time to use fexecve instead
of execve when spawning children. Using fexecve closes a window
between checking the security context of an executable and spawning
it, but unfortunately the kernel displays stale information in the

View File

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

View File

@ -783,11 +783,15 @@ sensor:modalias:acpi:BOSC0200*:dmi:*:bvrTP15-VT5.2.1.3:*:svnTrekStor*:pnSurfTabt
sensor:modalias:acpi:KIOX010A*:dmi:*:svnTREKSTOR:pnPrimebookC11B:*
sensor:modalias:acpi:KIOX010A*:dmi:*:svnTREKSTOR:pnPRIMEBOOKC11B:*
sensor:modalias:acpi:KIOX010A*:dmi:*:svnTREKSTOR:pnYourbookC11B:*
sensor:modalias:acpi:KIOX010A*:dmi:*:svnTREKSTOR:pnYOURBOOKC11B:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, -1
ACCEL_LOCATION=display
sensor:modalias:acpi:KIOX020A*:dmi:*:svnTREKSTOR:pnPrimebookC11B:*
sensor:modalias:acpi:KIOX020A*:dmi:*:svnTREKSTOR:pnPRIMEBOOKC11B:*
sensor:modalias:acpi:KIOX020A*:dmi:*:svnTREKSTOR:pnYourbookC11B:*
sensor:modalias:acpi:KIOX020A*:dmi:*:svnTREKSTOR:pnYOURBOOKC11B:*
ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
ACCEL_LOCATION=base

View File

@ -2450,6 +2450,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMPreference = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@ -2974,6 +2976,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
<!--property ManagedOOMPreference is not documented!-->
<!--property EnvironmentFiles is not documented!-->
<!--property PassEnvironment is not documented!-->
@ -3538,6 +3542,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
<variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
<variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/>
@ -4204,6 +4210,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMPreference = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@ -4756,6 +4764,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
<!--property ManagedOOMPreference is not documented!-->
<!--property EnvironmentFiles is not documented!-->
<!--property PassEnvironment is not documented!-->
@ -5318,6 +5328,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
<variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
<variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/>
@ -5897,6 +5909,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMPreference = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@ -6377,6 +6391,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
<!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
<!--property ManagedOOMPreference is not documented!-->
<!--property EnvironmentFiles is not documented!-->
<!--property PassEnvironment is not documented!-->
@ -6857,6 +6873,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
<variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
<variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/>
@ -7557,6 +7575,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMPreference = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@ -8023,6 +8043,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
<!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
<!--property ManagedOOMPreference is not documented!-->
<!--property EnvironmentFiles is not documented!-->
<!--property PassEnvironment is not documented!-->
@ -8489,6 +8511,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
<variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
<variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/>
@ -9042,6 +9066,8 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMPreference = '...';
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
@ -9178,6 +9204,8 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
<!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
<!--property ManagedOOMPreference is not documented!-->
<!--Autogenerated cross-references for systemd.directives, do not edit-->
<variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.systemd1.Unit"/>
@ -9318,6 +9346,8 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
<!--End of Autogenerated section-->
<refsect2>
@ -9477,6 +9507,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMPreference = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s KillMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@ -9629,6 +9661,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
<!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
<!--property ManagedOOMPreference is not documented!-->
<!--property KillMode is not documented!-->
<!--property KillSignal is not documented!-->
@ -9795,6 +9829,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
<variablelist class="dbus-property" generated="True" extra-ref="KillMode"/>
<variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/>

View File

@ -913,6 +913,38 @@ DeviceAllow=/dev/loop-control
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>ManagedOOMPreference=none|avoid|omit</varname></term>
<listitem>
<para>Allows deprioritizing or omitting this unit's cgroup as a candidate when <command>systemd-oomd</command>
needs to act. Requires support for extended attributes (see
<citerefentry project='man-pages'><refentrytitle>xattr</refentrytitle><manvolnum>7</manvolnum></citerefentry>)
in order to use <option>avoid</option> or <option>omit</option>. Additionally, <command>systemd-oomd</command>
will ignore these extended attributes if the unit's cgroup is not owned by the root user.</para>
<para>If this property is set to <option>avoid</option>, the service manager will set the
"user.oomd_avoid" extended attribute on the unit's cgroup to "1". If <command>systemd-oomd</command> sees
this extended attribute on a cgroup set to "1" when choosing between candidates, it will only select the
cgroup with "user.oomd_avoid" if there are no other viable candidates.</para>
<para>If this property is set to <option>omit</option>, the service manager will set the "user.oomd_omit"
extended attribute on the unit's cgroup to "1". If <command>systemd-oomd</command> sees the this extended
attribute on the cgroup set to "1", it will ignore the cgroup as a candidate and will not perform any actions
on the cgroup.</para>
<para>It is recommended to use <option>avoid</option> and <option>omit</option> sparingly as it can adversely
affect <command>systemd-oomd</command>'s kill behavior. Also note that these extended attributes are not
applied recursively to cgroups under this unit's cgroup.</para>
<para>Defaults to <option>none</option> which means no extended attributes will be set and systemd-oomd will
sort this unit's cgroup as defined in
<citerefentry><refentrytitle>systemd-oomd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
and <citerefentry><refentrytitle>oomd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> (if this
unit's cgroup becomes a candidate).</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -110,7 +110,7 @@ KERNEL=="sr*", ENV{DISK_EJECT_REQUEST}!="?*", ENV{ID_CDROM_MEDIA_TRACK_COUNT_DAT
IMPORT{builtin}="blkid --noraid"
# probe filesystem metadata of disks
KERNEL!="sr*", IMPORT{builtin}="blkid"
KERNEL!="sr*|mmcblk[0-9]boot[0-9]", IMPORT{builtin}="blkid"
# by-label/by-uuid links (filesystem metadata)
ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{ID_FS_UUID_ENC}=="?*", SYMLINK+="disk/by-uuid/$env{ID_FS_UUID_ENC}"

View File

@ -635,6 +635,20 @@ int cg_get_xattr_malloc(const char *controller, const char *path, const char *na
return r;
}
int cg_get_xattr_bool(const char *controller, const char *path, const char *name) {
_cleanup_free_ char *val = NULL;
int r;
assert(path);
assert(name);
r = cg_get_xattr_malloc(controller, path, name, &val);
if (r < 0)
return r;
return parse_boolean(val);
}
int cg_remove_xattr(const char *controller, const char *path, const char *name) {
_cleanup_free_ char *fs = NULL;
int r;
@ -1703,6 +1717,25 @@ int cg_get_attribute_as_bool(const char *controller, const char *path, const cha
return 0;
}
int cg_get_owner(const char *controller, const char *path, uid_t *ret_uid) {
_cleanup_free_ char *f = NULL;
struct stat stats;
int r;
assert(ret_uid);
r = cg_get_path(controller, path, NULL, &f);
if (r < 0)
return r;
r = stat(f, &stats);
if (r < 0)
return -errno;
*ret_uid = stats.st_uid;
return 0;
}
int cg_get_keyed_attribute_full(
const char *controller,
const char *path,
@ -2185,3 +2218,11 @@ static const char* const managed_oom_mode_table[_MANAGED_OOM_MODE_MAX] = {
};
DEFINE_STRING_TABLE_LOOKUP(managed_oom_mode, ManagedOOMMode);
static const char* const managed_oom_preference_table[_MANAGED_OOM_PREFERENCE_MAX] = {
[MANAGED_OOM_PREFERENCE_NONE] = "none",
[MANAGED_OOM_PREFERENCE_AVOID] = "avoid",
[MANAGED_OOM_PREFERENCE_OMIT] = "omit",
};
DEFINE_STRING_TABLE_LOOKUP(managed_oom_preference, ManagedOOMPreference);

View File

@ -212,10 +212,13 @@ int cg_get_attribute_as_uint64(const char *controller, const char *path, const c
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_get_owner(const char *controller, const char *path, uid_t *ret_uid);
int cg_set_xattr(const char *controller, const char *path, const char *name, const void *value, size_t size, int flags);
int cg_get_xattr(const char *controller, const char *path, const char *name, void *value, size_t size);
int cg_get_xattr_malloc(const char *controller, const char *path, const char *name, char **ret);
/* Returns negative on error, and 0 or 1 on success for the bool value */
int cg_get_xattr_bool(const char *controller, const char *path, const char *name);
int cg_remove_xattr(const char *controller, const char *path, const char *name);
int cg_install_release_agent(const char *controller, const char *agent);
@ -288,3 +291,14 @@ typedef enum ManagedOOMMode {
const char* managed_oom_mode_to_string(ManagedOOMMode m) _const_;
ManagedOOMMode managed_oom_mode_from_string(const char *s) _pure_;
typedef enum ManagedOOMPreference {
MANAGED_OOM_PREFERENCE_NONE = 0,
MANAGED_OOM_PREFERENCE_AVOID = 1,
MANAGED_OOM_PREFERENCE_OMIT = 2,
_MANAGED_OOM_PREFERENCE_MAX,
_MANAGED_OOM_PREFERENCE_INVALID = -1
} ManagedOOMPreference;
const char* managed_oom_preference_to_string(ManagedOOMPreference a) _const_;
ManagedOOMPreference managed_oom_preference_from_string(const char *s) _pure_;

View File

@ -131,6 +131,7 @@ void cgroup_context_init(CGroupContext *c) {
.moom_swap = MANAGED_OOM_AUTO,
.moom_mem_pressure = MANAGED_OOM_AUTO,
.moom_preference = MANAGED_OOM_PREFERENCE_NONE,
};
}
@ -417,7 +418,8 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
"%sDelegate: %s\n"
"%sManagedOOMSwap: %s\n"
"%sManagedOOMMemoryPressure: %s\n"
"%sManagedOOMMemoryPressureLimit: %" PRIu32 ".%02" PRIu32 "%%\n",
"%sManagedOOMMemoryPressureLimit: %" PRIu32 ".%02" PRIu32 "%%\n"
"%sManagedOOMPreference: %s%%\n",
prefix, yes_no(c->cpu_accounting),
prefix, yes_no(c->io_accounting),
prefix, yes_no(c->blockio_accounting),
@ -450,7 +452,8 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
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_permyriad / 100, c->moom_mem_pressure_limit_permyriad % 100);
prefix, c->moom_mem_pressure_limit_permyriad / 100, c->moom_mem_pressure_limit_permyriad % 100,
prefix, managed_oom_preference_to_string(c->moom_preference));
if (c->delegate) {
_cleanup_free_ char *t = NULL;
@ -600,6 +603,41 @@ int cgroup_add_device_allow(CGroupContext *c, const char *dev, const char *mode)
UNIT_DEFINE_ANCESTOR_MEMORY_LOOKUP(memory_low);
UNIT_DEFINE_ANCESTOR_MEMORY_LOOKUP(memory_min);
void cgroup_oomd_xattr_apply(Unit *u, const char *cgroup_path) {
CGroupContext *c;
int r;
assert(u);
c = unit_get_cgroup_context(u);
if (!c)
return;
if (c->moom_preference == MANAGED_OOM_PREFERENCE_OMIT) {
r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, "user.oomd_omit", "1", 1, 0);
if (r < 0)
log_unit_debug_errno(u, r, "Failed to set oomd_omit flag on control group %s, ignoring: %m", cgroup_path);
}
if (c->moom_preference == MANAGED_OOM_PREFERENCE_AVOID) {
r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, "user.oomd_avoid", "1", 1, 0);
if (r < 0)
log_unit_debug_errno(u, r, "Failed to set oomd_avoid flag on control group %s, ignoring: %m", cgroup_path);
}
if (c->moom_preference != MANAGED_OOM_PREFERENCE_AVOID) {
r = cg_remove_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, "user.oomd_avoid");
if (r != -ENODATA)
log_unit_debug_errno(u, r, "Failed to remove oomd_avoid flag on control group %s, ignoring: %m", cgroup_path);
}
if (c->moom_preference != MANAGED_OOM_PREFERENCE_OMIT) {
r = cg_remove_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, "user.oomd_omit");
if (r != -ENODATA)
log_unit_debug_errno(u, r, "Failed to remove oomd_omit flag on control group %s, ignoring: %m", cgroup_path);
}
}
static void cgroup_xattr_apply(Unit *u) {
char ids[SD_ID128_STRING_MAX];
int r;
@ -630,6 +668,8 @@ static void cgroup_xattr_apply(Unit *u) {
if (r != -ENODATA)
log_unit_debug_errno(u, r, "Failed to remove delegate flag on control group %s, ignoring: %m", u->cgroup_path);
}
cgroup_oomd_xattr_apply(u, u->cgroup_path);
}
static int lookup_block_device(const char *p, dev_t *ret) {
@ -2746,7 +2786,7 @@ int unit_check_oomd_kill(Unit *u) {
else if (r == 0)
return 0;
r = cg_get_xattr_malloc(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "user.systemd_oomd_kill", &value);
r = cg_get_xattr_malloc(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "user.oomd_kill", &value);
if (r < 0 && r != -ENODATA)
return r;
@ -3737,12 +3777,6 @@ int unit_cgroup_freezer_action(Unit *u, FreezerAction action) {
return 1;
}
static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = {
[CGROUP_DEVICE_POLICY_AUTO] = "auto",
[CGROUP_DEVICE_POLICY_CLOSED] = "closed",
[CGROUP_DEVICE_POLICY_STRICT] = "strict",
};
int unit_get_cpuset(Unit *u, CPUSet *cpus, const char *name) {
_cleanup_free_ char *v = NULL;
int r;
@ -3771,6 +3805,12 @@ int unit_get_cpuset(Unit *u, CPUSet *cpus, const char *name) {
return parse_cpu_set_full(v, cpus, false, NULL, NULL, 0, NULL);
}
static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = {
[CGROUP_DEVICE_POLICY_AUTO] = "auto",
[CGROUP_DEVICE_POLICY_CLOSED] = "closed",
[CGROUP_DEVICE_POLICY_STRICT] = "strict",
};
DEFINE_STRING_TABLE_LOOKUP(cgroup_device_policy, CGroupDevicePolicy);
static const char* const freezer_action_table[_FREEZER_ACTION_MAX] = {

View File

@ -164,6 +164,7 @@ struct CGroupContext {
ManagedOOMMode moom_swap;
ManagedOOMMode moom_mem_pressure;
uint32_t moom_mem_pressure_limit_permyriad;
ManagedOOMPreference moom_preference;
};
/* Used when querying IP accounting data */
@ -204,6 +205,8 @@ void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockI
int cgroup_add_device_allow(CGroupContext *c, const char *dev, const char *mode);
void cgroup_oomd_xattr_apply(Unit *u, const char *cgroup_path);
CGroupMask unit_get_own_mask(Unit *u);
CGroupMask unit_get_delegate_mask(Unit *u);
CGroupMask unit_get_members_mask(Unit *u);

View File

@ -21,6 +21,7 @@ BUS_DEFINE_PROPERTY_GET(bus_property_get_tasks_max, "t", TasksMax, tasks_max_res
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_managed_oom_mode, managed_oom_mode, ManagedOOMMode);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_managed_oom_preference, managed_oom_preference, ManagedOOMPreference);
static int property_get_cgroup_mask(
sd_bus *bus,
@ -395,6 +396,7 @@ const sd_bus_vtable bus_cgroup_vtable[] = {
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("ManagedOOMMemoryPressureLimitPermyriad", "u", NULL, offsetof(CGroupContext, moom_mem_pressure_limit_permyriad), 0),
SD_BUS_PROPERTY("ManagedOOMPreference", "s", property_get_managed_oom_preference, offsetof(CGroupContext, moom_preference), 0),
SD_BUS_VTABLE_END
};
@ -1720,6 +1722,26 @@ int bus_cgroup_set_property(
return 1;
}
if (streq(name, "ManagedOOMPreference")) {
ManagedOOMPreference p;
const char *pref;
r = sd_bus_message_read(message, "s", &pref);
if (r < 0)
return r;
p = managed_oom_preference_from_string(pref);
if (p < 0)
return -EINVAL;
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->moom_preference = p;
unit_write_settingf(u, flags, name, "ManagedOOMPreference=%s", pref);
}
return 1;
}
if (streq(name, "DisableControllers") || (u->transient && u->load_state == UNIT_STUB))
return bus_cgroup_set_transient_property(u, c, name, message, flags, error);

View File

@ -2356,7 +2356,8 @@ int bus_unit_validate_load_state(Unit *u, sd_bus_error *error) {
return sd_bus_error_setf(error, BUS_ERROR_BAD_UNIT_SETTING, "Unit %s has a bad unit file setting.", u->id);
case UNIT_ERROR: /* Only show .load_error in UNIT_ERROR state */
return sd_bus_error_set_errnof(error, u->load_error, "Unit %s failed to load properly: %m.", u->id);
return sd_bus_error_set_errnof(error, u->load_error,
"Unit %s failed to load properly, please adjust/correct and reload service manager: %m", u->id);
case UNIT_MASKED:
return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit %s is masked.", u->id);

View File

@ -4706,6 +4706,10 @@ int exec_spawn(Unit *unit,
r = cg_create(SYSTEMD_CGROUP_CONTROLLER, subcgroup_path);
if (r < 0)
return log_unit_error_errno(unit, r, "Failed to create control group '%s': %m", subcgroup_path);
/* Normally we would not propagate the oomd xattrs to children but since we created this
* sub-cgroup internally we should do it. */
cgroup_oomd_xattr_apply(unit, subcgroup_path);
}
}

View File

@ -230,6 +230,7 @@ $1.IPEgressFilterPath, config_parse_ip_filter_bpf_progs,
$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.ManagedOOMMemoryPressureLimit, config_parse_managed_oom_mem_pressure_limit, 0, offsetof($1, cgroup_context.moom_mem_pressure_limit_permyriad)
$1.ManagedOOMPreference, config_parse_managed_oom_preference, 0, offsetof($1, cgroup_context.moom_preference)
$1.NetClass, config_parse_warn_compat, DISABLED_LEGACY, 0'
)m4_dnl
Unit.Description, config_parse_unit_string_printf, 0, offsetof(Unit, description)

View File

@ -133,6 +133,7 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceR
DEFINE_CONFIG_PARSE_ENUM(config_parse_service_timeout_failure_mode, service_timeout_failure_mode, ServiceTimeoutFailureMode, "Failed to parse timeout failure mode");
DEFINE_CONFIG_PARSE_ENUM(config_parse_socket_bind, socket_address_bind_ipv6_only_or_bool, SocketAddressBindIPv6Only, "Failed to parse bind IPv6 only value");
DEFINE_CONFIG_PARSE_ENUM(config_parse_oom_policy, oom_policy, OOMPolicy, "Failed to parse OOM policy");
DEFINE_CONFIG_PARSE_ENUM(config_parse_managed_oom_preference, managed_oom_preference, ManagedOOMPreference, "Failed to parse ManagedOOMPreference=");
DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_ip_tos, ip_tos, int, -1, "Failed to parse IP TOS value");
DEFINE_CONFIG_PARSE_PTR(config_parse_blockio_weight, cg_blkio_weight_parse, uint64_t, "Invalid block IO weight");
DEFINE_CONFIG_PARSE_PTR(config_parse_cg_weight, cg_weight_parse, uint64_t, "Invalid weight");

View File

@ -78,6 +78,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_tasks_max);
CONFIG_PARSER_PROTOTYPE(config_parse_delegate);
CONFIG_PARSER_PROTOTYPE(config_parse_managed_oom_mode);
CONFIG_PARSER_PROTOTYPE(config_parse_managed_oom_mem_pressure_limit);
CONFIG_PARSER_PROTOTYPE(config_parse_managed_oom_preference);
CONFIG_PARSER_PROTOTYPE(config_parse_device_policy);
CONFIG_PARSER_PROTOTYPE(config_parse_device_allow);
CONFIG_PARSER_PROTOTYPE(config_parse_io_device_latency);

View File

@ -326,6 +326,7 @@ static int address_add_foreign(Link *link, const Address *in, Address **ret) {
}
static int address_add(Link *link, const Address *in, Address **ret) {
bool is_new = false;
Address *address;
int r;
@ -338,6 +339,7 @@ static int address_add(Link *link, const Address *in, Address **ret) {
r = address_add_internal(link, &link->addresses, in, &address);
if (r < 0)
return r;
is_new = true;
} else if (r == 0) {
/* Take over a foreign address */
r = set_ensure_put(&link->addresses, &address_hash_ops, address);
@ -353,8 +355,7 @@ static int address_add(Link *link, const Address *in, Address **ret) {
if (ret)
*ret = address;
return 0;
return is_new;
}
static int address_update(Address *address, const Address *src) {
@ -517,6 +518,37 @@ static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link
return 1;
}
static int address_set_netlink_message(const Address *address, sd_netlink_message *req, Link *link) {
int r;
assert(address);
assert(req);
assert(link);
r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
if (r < 0)
return log_link_error_errno(link, r, "Could not set prefixlen: %m");
/* On remove, only IFA_F_MANAGETEMPADDR flag for IPv6 addresses are used. But anyway, set all
* flags here unconditionally. Without setting the flag, the template addresses generated by
* kernel will not be removed automatically when the main address is removed. */
r = sd_rtnl_message_addr_set_flags(req, address->flags & 0xff);
if (r < 0)
return log_link_error_errno(link, r, "Could not set flags: %m");
if ((address->flags & ~0xff) != 0) {
r = sd_netlink_message_append_u32(req, IFA_FLAGS, address->flags);
if (r < 0)
return log_link_error_errno(link, r, "Could not set extended flags: %m");
}
r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr);
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m");
return 0;
}
int address_remove(
const Address *address,
Link *link,
@ -539,13 +571,9 @@ int address_remove(
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate RTM_DELADDR message: %m");
r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
r = address_set_netlink_message(address, req, link);
if (r < 0)
return log_link_error_errno(link, r, "Could not set prefixlen: %m");
r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr);
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m");
return r;
r = netlink_call_async(link->manager->rtnl, NULL, req,
callback ?: address_remove_handler,
@ -809,9 +837,8 @@ int address_configure(
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
Address *acquired_address, *a;
uint32_t flags;
bool update;
int r;
int r, k;
assert(address);
assert(IN_SET(address->family, AF_INET, AF_INET6));
@ -846,29 +873,14 @@ int address_configure(
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate RTM_NEWADDR message: %m");
r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
r = address_set_netlink_message(address, req, link);
if (r < 0)
return log_link_error_errno(link, r, "Could not set prefixlen: %m");
flags = address->flags | IFA_F_PERMANENT;
r = sd_rtnl_message_addr_set_flags(req, flags & 0xff);
if (r < 0)
return log_link_error_errno(link, r, "Could not set flags: %m");
if (flags & ~0xff) {
r = sd_netlink_message_append_u32(req, IFA_FLAGS, flags);
if (r < 0)
return log_link_error_errno(link, r, "Could not set extended flags: %m");
}
return r;
r = sd_rtnl_message_addr_set_scope(req, address->scope);
if (r < 0)
return log_link_error_errno(link, r, "Could not set scope: %m");
r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr);
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m");
if (in_addr_is_null(address->family, &address->in_addr_peer) == 0) {
r = netlink_message_append_in_addr_union(req, IFA_ADDRESS, address->family, &address->in_addr_peer);
if (r < 0)
@ -889,9 +901,9 @@ int address_configure(
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_CACHEINFO attribute: %m");
r = address_add(link, address, &a);
if (r < 0)
return log_link_error_errno(link, r, "Could not add address: %m");
k = address_add(link, address, &a);
if (k < 0)
return log_link_error_errno(link, k, "Could not add address: %m");
r = address_set_masquerade(a, true);
if (r < 0)
@ -914,7 +926,7 @@ int address_configure(
if (ret)
*ret = a;
return 1;
return k;
}
static int static_address_ready_callback(Address *address) {

View File

@ -137,7 +137,7 @@ static int dhcp6_pd_remove_old(Link *link, bool force) {
assert(link);
assert(link->manager);
if (!force && (link->dhcp6_pd_address_messages != 0 || link->dhcp6_pd_route_configured != 0))
if (!force && (link->dhcp6_pd_address_messages != 0 || link->dhcp6_pd_route_messages != 0))
return 0;
if (set_isempty(link->dhcp6_pd_addresses_old) && set_isempty(link->dhcp6_pd_routes_old))
@ -281,6 +281,8 @@ static int dhcp6_set_pd_route(Link *link, const union in_addr_union *prefix, con
r = route_configure(route, link, dhcp6_pd_route_handler, &ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to set DHCPv6 prefix route: %m");
if (r > 0)
link->dhcp6_pd_route_configured = false;
link->dhcp6_pd_route_messages++;
@ -394,6 +396,8 @@ static int dhcp6_set_pd_address(
r = address_configure(address, link, dhcp6_pd_address_handler, &ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to set DHCPv6 delegated prefix address: %m");
if (r > 0)
link->dhcp6_pd_address_configured = false;
link->dhcp6_pd_address_messages++;
@ -576,8 +580,6 @@ static int dhcp6_pd_prepare(Link *link) {
if (!link_dhcp6_pd_is_enabled(link))
return 0;
link->dhcp6_pd_address_configured = false;
link->dhcp6_pd_route_configured = false;
link->dhcp6_pd_prefixes_assigned = true;
while ((address = set_steal_first(link->dhcp6_pd_addresses))) {
@ -816,6 +818,8 @@ static int dhcp6_set_unreachable_route(Link *link, const union in_addr_union *ad
if (r < 0)
return log_link_error_errno(link, r, "Failed to set unreachable route for DHCPv6 delegated subnet %s/%u: %m",
strna(buf), prefixlen);
if (r > 0)
link->dhcp6_route_configured = false;
link->dhcp6_route_messages++;
@ -1038,6 +1042,8 @@ static int dhcp6_update_address(
if (r < 0)
return log_link_error_errno(link, r, "Failed to set DHCPv6 address %s/%u: %m",
strnull(buffer), addr->prefixlen);
if (r > 0)
link->dhcp6_address_configured = false;
link->dhcp6_address_messages++;
@ -1103,9 +1109,6 @@ static int dhcp6_lease_ip_acquired(sd_dhcp6_client *client, Link *link) {
Route *rt;
int r;
link->dhcp6_address_configured = false;
link->dhcp6_route_configured = false;
while ((a = set_steal_first(link->dhcp6_addresses))) {
r = set_ensure_put(&link->dhcp6_addresses_old, &address_hash_ops, a);
if (r < 0)

View File

@ -343,6 +343,8 @@ static int ndisc_route_configure(Route *route, Link *link, sd_ndisc_router *rt)
r = route_configure(route, link, ndisc_route_handler, &ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to set NDisc route: %m");
if (r > 0)
link->ndisc_routes_configured = false;
link->ndisc_routes_messages++;
@ -437,6 +439,8 @@ static int ndisc_address_configure(Address *address, Link *link, sd_ndisc_router
r = address_configure(address, link, ndisc_address_handler, &ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to set NDisc SLAAC address: %m");
if (r > 0)
link->ndisc_addresses_configured = false;
link->ndisc_addresses_messages++;
@ -1213,9 +1217,6 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
return 0;
}
link->ndisc_addresses_configured = false;
link->ndisc_routes_configured = false;
SET_FOREACH(na, link->ndisc_addresses)
if (IN6_ARE_ADDR_EQUAL(&na->router, &router.in6))
na->marked = true;

View File

@ -170,6 +170,7 @@ static int neighbor_add_internal(Link *link, Set **neighbors, const Neighbor *in
}
static int neighbor_add(Link *link, const Neighbor *in, Neighbor **ret) {
bool is_new = false;
Neighbor *neighbor;
int r;
@ -179,6 +180,7 @@ static int neighbor_add(Link *link, const Neighbor *in, Neighbor **ret) {
r = neighbor_add_internal(link, &link->neighbors, in, &neighbor);
if (r < 0)
return r;
is_new = true;
} else if (r == 0) {
/* Neighbor is foreign, claim it as recognized */
r = set_ensure_put(&link->neighbors, &neighbor_hash_ops, neighbor);
@ -188,12 +190,13 @@ static int neighbor_add(Link *link, const Neighbor *in, Neighbor **ret) {
set_remove(link->neighbors_foreign, neighbor);
} else if (r == 1) {
/* Neighbor already exists */
;
} else
return r;
if (ret)
*ret = neighbor;
return 0;
return is_new;
}
static int neighbor_add_foreign(Link *link, const Neighbor *in, Neighbor **ret) {
@ -279,7 +282,7 @@ static int neighbor_configure(Neighbor *neighbor, Link *link) {
if (r < 0)
return log_link_error_errno(link, r, "Could not add neighbor: %m");
return 0;
return r;
}
int link_set_neighbors(Link *link) {

View File

@ -188,6 +188,7 @@ static int nexthop_add_foreign(Link *link, NextHop *in, NextHop **ret) {
}
static int nexthop_add(Link *link, NextHop *in, NextHop **ret) {
bool is_new = false;
NextHop *nexthop;
int r;
@ -197,6 +198,7 @@ static int nexthop_add(Link *link, NextHop *in, NextHop **ret) {
r = nexthop_add_internal(link, &link->nexthops, in, &nexthop);
if (r < 0)
return r;
is_new = true;
} else if (r == 0) {
/* Take over a foreign nexthop */
r = set_ensure_put(&link->nexthops, &nexthop_hash_ops, nexthop);
@ -212,8 +214,7 @@ static int nexthop_add(Link *link, NextHop *in, NextHop **ret) {
if (ret)
*ret = nexthop;
return 0;
return is_new;
}
static int nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
@ -297,7 +298,7 @@ static int nexthop_configure(NextHop *nexthop, Link *link) {
if (r < 0)
return log_link_error_errno(link, r, "Could not add nexthop: %m");
return 1;
return r;
}
int link_set_nexthop(Link *link) {

View File

@ -549,6 +549,7 @@ static int route_add_foreign(Manager *manager, Link *link, const Route *in, Rout
static int route_add(Manager *manager, Link *link, const Route *in, const MultipathRoute *m, Route **ret) {
_cleanup_(route_freep) Route *tmp = NULL;
bool is_new = false;
Route *route;
int r;
@ -572,6 +573,7 @@ static int route_add(Manager *manager, Link *link, const Route *in, const Multip
r = route_add_internal(manager, link, link ? &link->routes : &manager->routes, in, &route);
if (r < 0)
return r;
is_new = true;
} else if (r == 0) {
/* Take over a foreign route */
if (link) {
@ -595,8 +597,7 @@ static int route_add(Manager *manager, Link *link, const Route *in, const Multip
if (ret)
*ret = route;
return 0;
return is_new;
}
static bool route_type_is_reject(const Route *route) {
@ -949,15 +950,15 @@ static int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdat
static int route_add_and_setup_timer(Link *link, const Route *route, const MultipathRoute *m, Route **ret) {
_cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL;
Route *nr;
int r;
int r, k;
assert(link);
assert(route);
if (route_type_is_reject(route))
r = route_add(link->manager, NULL, route, NULL, &nr);
k = route_add(link->manager, NULL, route, NULL, &nr);
else if (!m || m->ifindex == 0 || m->ifindex == link->ifindex)
r = route_add(NULL, link, route, m, &nr);
k = route_add(NULL, link, route, m, &nr);
else {
Link *link_gw;
@ -965,10 +966,10 @@ static int route_add_and_setup_timer(Link *link, const Route *route, const Multi
if (r < 0)
return log_link_error_errno(link, r, "Failed to get link with ifindex %d: %m", m->ifindex);
r = route_add(NULL, link_gw, route, m, &nr);
k = route_add(NULL, link_gw, route, m, &nr);
}
if (r < 0)
return log_link_error_errno(link, r, "Could not add route: %m");
if (k < 0)
return log_link_error_errno(link, k, "Could not add route: %m");
/* TODO: drop expiration handling once it can be pushed into the kernel */
if (nr->lifetime != USEC_INFINITY && !kernel_route_expiration_supported()) {
@ -984,7 +985,7 @@ static int route_add_and_setup_timer(Link *link, const Route *route, const Multi
if (ret)
*ret = nr;
return 0;
return k;
}
static int append_nexthop_one(const Route *route, const MultipathRoute *m, struct rtattr **rta, size_t offset) {
@ -1075,7 +1076,8 @@ int route_configure(
Route **ret) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
int r, k = 0;
Route *nr;
assert(link);
assert(link->manager);
@ -1163,14 +1165,9 @@ int route_configure(
return log_link_error_errno(link, r, "Could not append RTA_MULTIPATH attribute: %m");
if (ordered_set_isempty(route->multipath_routes)) {
Route *nr;
r = route_add_and_setup_timer(link, route, NULL, &nr);
if (r < 0)
return r;
if (ret)
*ret = nr;
k = route_add_and_setup_timer(link, route, NULL, &nr);
if (k < 0)
return k;
} else {
MultipathRoute *m;
@ -1180,6 +1177,8 @@ int route_configure(
r = route_add_and_setup_timer(link, route, m, NULL);
if (r < 0)
return r;
if (r > 0)
k = 1;
}
}
@ -1190,7 +1189,10 @@ int route_configure(
link_ref(link);
return 0;
if (ret)
*ret = nr;
return k;
}
static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {

View File

@ -326,6 +326,7 @@ static int routing_policy_rule_get(Manager *m, const RoutingPolicyRule *rule, Ro
static int routing_policy_rule_add(Manager *m, const RoutingPolicyRule *in, int family, RoutingPolicyRule **ret) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL;
RoutingPolicyRule *existing;
bool is_new = false;
int r;
assert(m);
@ -353,6 +354,7 @@ static int routing_policy_rule_add(Manager *m, const RoutingPolicyRule *in, int
rule->manager = m;
existing = TAKE_PTR(rule);
is_new = true;
} else if (r == 0) {
/* Take over a foreign rule. */
r = set_ensure_put(&m->rules, &routing_policy_rule_hash_ops, existing);
@ -369,8 +371,7 @@ static int routing_policy_rule_add(Manager *m, const RoutingPolicyRule *in, int
if (ret)
*ret = existing;
return 0;
return is_new;
}
static int routing_policy_rule_consume_foreign(Manager *m, RoutingPolicyRule *rule) {
@ -635,7 +636,7 @@ static int routing_policy_rule_configure_internal(const RoutingPolicyRule *rule,
if (r < 0)
return log_link_error_errno(link, r, "Could not add rule: %m");
return 1;
return r;
}
static int routing_policy_rule_configure(const RoutingPolicyRule *rule, Link *link) {

View File

@ -93,7 +93,7 @@ static int process_managed_oom_reply(
m->monitored_swap_cgroup_contexts : m->monitored_mem_pressure_cgroup_contexts;
if (reply.mode == MANAGED_OOM_AUTO) {
(void) oomd_cgroup_context_free(hashmap_remove(monitor_hm, reply.path));
(void) oomd_cgroup_context_free(hashmap_remove(monitor_hm, empty_to_root(reply.path)));
continue;
}
@ -109,7 +109,7 @@ static int process_managed_oom_reply(
}
}
ret = oomd_insert_cgroup_context(NULL, monitor_hm, reply.path);
ret = oomd_insert_cgroup_context(NULL, monitor_hm, empty_to_root(reply.path));
if (ret == -ENOMEM) {
r = ret;
goto finish;
@ -117,7 +117,7 @@ static int process_managed_oom_reply(
/* Always update the limit in case it was changed. For non-memory pressure detection the value is
* ignored so always updating it here is not a problem. */
ctx = hashmap_get(monitor_hm, reply.path);
ctx = hashmap_get(monitor_hm, empty_to_root(reply.path));
if (ctx)
ctx->mem_pressure_limit = limit;
}

View File

@ -3,7 +3,6 @@
#include <sys/xattr.h>
#include <unistd.h>
#include "cgroup-util.h"
#include "fd-util.h"
#include "format-util.h"
#include "oomd-util.h"
@ -159,7 +158,8 @@ int oomd_sort_cgroup_contexts(Hashmap *h, oomd_compare_t compare_func, const cha
return -ENOMEM;
HASHMAP_FOREACH(item, h) {
if (item->path && prefix && !path_startswith(item->path, prefix))
/* Skip over cgroups that are not valid candidates or are explicitly marked for omission */
if ((item->path && prefix && !path_startswith(item->path, prefix)) || item->preference == MANAGED_OOM_PREFERENCE_OMIT)
continue;
sorted[k++] = item;
@ -201,9 +201,9 @@ int oomd_cgroup_kill(const char *path, bool recurse, bool dry_run) {
if (r < 0)
return r;
r = increment_oomd_xattr(path, "user.systemd_oomd_kill", set_size(pids_killed));
r = increment_oomd_xattr(path, "user.oomd_kill", set_size(pids_killed));
if (r < 0)
log_debug_errno(r, "Failed to set user.systemd_oomd_kill on kill: %m");
log_debug_errno(r, "Failed to set user.oomd_kill on kill: %m");
return set_size(pids_killed) != 0;
}
@ -214,13 +214,15 @@ int oomd_kill_by_pgscan(Hashmap *h, const char *prefix, bool dry_run) {
assert(h);
r = oomd_sort_cgroup_contexts(h, compare_pgscan, prefix, &sorted);
r = oomd_sort_cgroup_contexts(h, compare_pgscan_and_memory_usage, prefix, &sorted);
if (r < 0)
return r;
for (int i = 0; i < r; i++) {
if (sorted[i]->pgscan == 0)
break;
/* Skip cgroups with no reclaim and memory usage; it won't alleviate pressure. */
/* Don't break since there might be "avoid" cgroups at the end. */
if (sorted[i]->pgscan == 0 && sorted[i]->current_memory_usage == 0)
continue;
r = oomd_cgroup_kill(sorted[i]->path, true, dry_run);
if (r > 0 || r == -ENOMEM)
@ -243,8 +245,10 @@ int oomd_kill_by_swap_usage(Hashmap *h, bool dry_run) {
/* Try to kill cgroups with non-zero swap usage until we either succeed in
* killing or we get to a cgroup with no swap usage. */
for (int i = 0; i < r; i++) {
/* Skip over cgroups with no resource usage. Don't break since there might be "avoid"
* cgroups at the end. */
if (sorted[i]->swap_usage == 0)
break;
continue;
r = oomd_cgroup_kill(sorted[i]->path, true, dry_run);
if (r > 0 || r == -ENOMEM)
@ -258,6 +262,7 @@ int oomd_cgroup_context_acquire(const char *path, OomdCGroupContext **ret) {
_cleanup_(oomd_cgroup_context_freep) OomdCGroupContext *ctx = NULL;
_cleanup_free_ char *p = NULL, *val = NULL;
bool is_root;
uid_t uid;
int r;
assert(path);
@ -268,6 +273,7 @@ int oomd_cgroup_context_acquire(const char *path, OomdCGroupContext **ret) {
return -ENOMEM;
is_root = empty_or_root(path);
ctx->preference = MANAGED_OOM_PREFERENCE_NONE;
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, "memory.pressure", &p);
if (r < 0)
@ -277,6 +283,23 @@ int oomd_cgroup_context_acquire(const char *path, OomdCGroupContext **ret) {
if (r < 0)
return log_debug_errno(r, "Error parsing memory pressure from %s: %m", p);
r = cg_get_owner(SYSTEMD_CGROUP_CONTROLLER, path, &uid);
if (r < 0)
log_debug_errno(r, "Failed to get owner/group from %s: %m", path);
else if (uid == 0) {
/* Ignore most errors when reading the xattr since it is usually unset and cgroup xattrs are only used
* as an optional feature of systemd-oomd (and the system might not even support them). */
r = cg_get_xattr_bool(SYSTEMD_CGROUP_CONTROLLER, path, "user.oomd_avoid");
if (r == -ENOMEM)
return r;
ctx->preference = r == 1 ? MANAGED_OOM_PREFERENCE_AVOID : ctx->preference;
r = cg_get_xattr_bool(SYSTEMD_CGROUP_CONTROLLER, path, "user.oomd_omit");
if (r == -ENOMEM)
return r;
ctx->preference = r == 1 ? MANAGED_OOM_PREFERENCE_OMIT : ctx->preference;
}
if (is_root) {
r = procfs_memory_get_used(&ctx->current_memory_usage);
if (r < 0)

View File

@ -3,6 +3,7 @@
#include <stdbool.h>
#include "cgroup-util.h"
#include "hashmap.h"
#include "psi-util.h"
@ -29,6 +30,8 @@ struct OomdCGroupContext {
uint64_t last_pgscan;
uint64_t pgscan;
ManagedOOMPreference preference;
/* These are only used by oomd_pressure_above for acting on high memory pressure. */
loadavg_t mem_pressure_limit;
usec_t mem_pressure_duration_usec;
@ -61,17 +64,35 @@ bool oomd_memory_reclaim(Hashmap *h);
/* Returns true if the amount of swap free is below the percentage of swap specified by `threshold_percent`. */
bool oomd_swap_free_below(const OomdSystemContext *ctx, uint64_t threshold_percent);
static inline int compare_pgscan(OomdCGroupContext * const *c1, OomdCGroupContext * const *c2) {
/* The compare functions will sort from largest to smallest, putting all the contexts with "avoid" at the end
* (after the smallest values). */
static inline int compare_pgscan_and_memory_usage(OomdCGroupContext * const *c1, OomdCGroupContext * const *c2) {
int r;
assert(c1);
assert(c2);
return CMP((*c2)->pgscan, (*c1)->pgscan);
r = CMP((*c1)->preference, (*c2)->preference);
if (r != 0)
return r;
r = CMP((*c2)->pgscan, (*c1)->pgscan);
if (r != 0)
return r;
return CMP((*c2)->current_memory_usage, (*c1)->current_memory_usage);
}
static inline int compare_swap_usage(OomdCGroupContext * const *c1, OomdCGroupContext * const *c2) {
int r;
assert(c1);
assert(c2);
r = CMP((*c1)->preference, (*c2)->preference);
if (r != 0)
return r;
return CMP((*c2)->swap_usage, (*c1)->swap_usage);
}

View File

@ -79,7 +79,7 @@ static void test_oomd_cgroup_kill(void) {
sleep(2);
assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, cgroup) == true);
assert_se(cg_get_xattr_malloc(SYSTEMD_CGROUP_CONTROLLER, cgroup, "user.systemd_oomd_kill", &v) >= 0);
assert_se(cg_get_xattr_malloc(SYSTEMD_CGROUP_CONTROLLER, cgroup, "user.oomd_kill", &v) >= 0);
assert_se(memcmp(v, i == 0 ? "2" : "4", 2) == 0);
}
}
@ -89,6 +89,8 @@ static void test_oomd_cgroup_context_acquire_and_insert(void) {
_cleanup_(oomd_cgroup_context_freep) OomdCGroupContext *ctx = NULL;
_cleanup_free_ char *cgroup = NULL;
OomdCGroupContext *c1, *c2;
bool test_xattrs;
int r;
if (geteuid() != 0)
return (void) log_tests_skipped("not root");
@ -101,6 +103,16 @@ static void test_oomd_cgroup_context_acquire_and_insert(void) {
assert_se(cg_pid_get_path(NULL, 0, &cgroup) >= 0);
/* If we don't have permissions to set xattrs we're likely in a userns or missing capabilities
* so skip the xattr portions of the test. */
r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup, "user.oomd_test", "1", 1, 0);
test_xattrs = !ERRNO_IS_PRIVILEGE(r) && !ERRNO_IS_NOT_SUPPORTED(r);
if (test_xattrs) {
assert_se(cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup, "user.oomd_omit", "1", 1, 0) >= 0);
assert_se(cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup, "user.oomd_avoid", "1", 1, 0) >= 0);
}
assert_se(oomd_cgroup_context_acquire(cgroup, &ctx) == 0);
assert_se(streq(ctx->path, cgroup));
@ -110,12 +122,28 @@ static void test_oomd_cgroup_context_acquire_and_insert(void) {
assert_se(ctx->swap_usage == 0);
assert_se(ctx->last_pgscan == 0);
assert_se(ctx->pgscan == 0);
/* omit takes precedence over avoid when both are set to true */
if (test_xattrs)
assert_se(ctx->preference == MANAGED_OOM_PREFERENCE_OMIT);
else
assert_se(ctx->preference == MANAGED_OOM_PREFERENCE_NONE);
ctx = oomd_cgroup_context_free(ctx);
/* also check when only avoid is set to true */
if (test_xattrs) {
assert_se(cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup, "user.oomd_omit", "0", 1, 0) >= 0);
assert_se(cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup, "user.oomd_avoid", "1", 1, 0) >= 0);
}
assert_se(oomd_cgroup_context_acquire(cgroup, &ctx) == 0);
if (test_xattrs)
assert_se(ctx->preference == MANAGED_OOM_PREFERENCE_AVOID);
ctx = oomd_cgroup_context_free(ctx);
/* Test the root cgroup */
assert_se(oomd_cgroup_context_acquire("", &ctx) == 0);
assert_se(streq(ctx->path, "/"));
assert_se(ctx->current_memory_usage > 0);
assert_se(ctx->preference == MANAGED_OOM_PREFERENCE_NONE);
/* Test hashmap inserts */
assert_se(h1 = hashmap_new(&oomd_cgroup_ctx_hash_ops));
@ -137,6 +165,14 @@ static void test_oomd_cgroup_context_acquire_and_insert(void) {
assert_se(c2->last_pgscan == 5555);
assert_se(c2->mem_pressure_limit == 6789);
assert_se(c2->last_hit_mem_pressure_limit == 42);
/* Assert that avoid/omit are not set if the cgroup is not owned by root */
if (test_xattrs) {
ctx = oomd_cgroup_context_free(ctx);
assert_se(cg_set_access(SYSTEMD_CGROUP_CONTROLLER, cgroup, 65534, 0) >= 0);
assert_se(oomd_cgroup_context_acquire(cgroup, &ctx) == 0);
assert_se(ctx->preference == MANAGED_OOM_PREFERENCE_NONE);
}
}
static void test_oomd_system_context_acquire(void) {
@ -287,21 +323,35 @@ static void test_oomd_sort_cgroups(void) {
char **paths = STRV_MAKE("/herp.slice",
"/herp.slice/derp.scope",
"/herp.slice/derp.scope/sheep.service",
"/zupa.slice");
"/zupa.slice",
"/omitted.slice",
"/avoid.slice");
OomdCGroupContext ctx[4] = {
OomdCGroupContext ctx[6] = {
{ .path = paths[0],
.swap_usage = 20,
.pgscan = 60 },
.pgscan = 60,
.current_memory_usage = 10 },
{ .path = paths[1],
.swap_usage = 60,
.pgscan = 40 },
.pgscan = 40,
.current_memory_usage = 20 },
{ .path = paths[2],
.swap_usage = 40,
.pgscan = 20 },
.pgscan = 40,
.current_memory_usage = 40 },
{ .path = paths[3],
.swap_usage = 10,
.pgscan = 80 },
.pgscan = 80,
.current_memory_usage = 10 },
{ .path = paths[4],
.swap_usage = 90,
.pgscan = 100,
.preference = MANAGED_OOM_PREFERENCE_OMIT },
{ .path = paths[5],
.swap_usage = 99,
.pgscan = 200,
.preference = MANAGED_OOM_PREFERENCE_AVOID },
};
assert_se(h = hashmap_new(&string_hash_ops));
@ -310,26 +360,32 @@ static void test_oomd_sort_cgroups(void) {
assert_se(hashmap_put(h, "/herp.slice/derp.scope", &ctx[1]) >= 0);
assert_se(hashmap_put(h, "/herp.slice/derp.scope/sheep.service", &ctx[2]) >= 0);
assert_se(hashmap_put(h, "/zupa.slice", &ctx[3]) >= 0);
assert_se(hashmap_put(h, "/omitted.slice", &ctx[4]) >= 0);
assert_se(hashmap_put(h, "/avoid.slice", &ctx[5]) >= 0);
assert_se(oomd_sort_cgroup_contexts(h, compare_swap_usage, NULL, &sorted_cgroups) == 4);
assert_se(oomd_sort_cgroup_contexts(h, compare_swap_usage, NULL, &sorted_cgroups) == 5);
assert_se(sorted_cgroups[0] == &ctx[1]);
assert_se(sorted_cgroups[1] == &ctx[2]);
assert_se(sorted_cgroups[2] == &ctx[0]);
assert_se(sorted_cgroups[3] == &ctx[3]);
assert_se(sorted_cgroups[4] == &ctx[5]);
sorted_cgroups = mfree(sorted_cgroups);
assert_se(oomd_sort_cgroup_contexts(h, compare_pgscan, NULL, &sorted_cgroups) == 4);
assert_se(oomd_sort_cgroup_contexts(h, compare_pgscan_and_memory_usage, NULL, &sorted_cgroups) == 5);
assert_se(sorted_cgroups[0] == &ctx[3]);
assert_se(sorted_cgroups[1] == &ctx[0]);
assert_se(sorted_cgroups[2] == &ctx[1]);
assert_se(sorted_cgroups[3] == &ctx[2]);
assert_se(sorted_cgroups[2] == &ctx[2]);
assert_se(sorted_cgroups[3] == &ctx[1]);
assert_se(sorted_cgroups[4] == &ctx[5]);
sorted_cgroups = mfree(sorted_cgroups);
assert_se(oomd_sort_cgroup_contexts(h, compare_pgscan, "/herp.slice/derp.scope", &sorted_cgroups) == 2);
assert_se(sorted_cgroups[0] == &ctx[1]);
assert_se(sorted_cgroups[1] == &ctx[2]);
assert_se(oomd_sort_cgroup_contexts(h, compare_pgscan_and_memory_usage, "/herp.slice/derp.scope", &sorted_cgroups) == 2);
assert_se(sorted_cgroups[0] == &ctx[2]);
assert_se(sorted_cgroups[1] == &ctx[1]);
assert_se(sorted_cgroups[2] == 0);
assert_se(sorted_cgroups[3] == 0);
assert_se(sorted_cgroups[4] == 0);
assert_se(sorted_cgroups[5] == 0);
sorted_cgroups = mfree(sorted_cgroups);
}

View File

@ -435,7 +435,8 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons
if (STR_IN_SET(field, "DevicePolicy",
"Slice",
"ManagedOOMSwap",
"ManagedOOMMemoryPressure"))
"ManagedOOMMemoryPressure",
"ManagedOOMPreference"))
return bus_append_string(m, field, eq);
if (STR_IN_SET(field, "ManagedOOMMemoryPressureLimit")) {

View File

@ -73,6 +73,7 @@ int main(int argc, char **argv) {
test_table(log_target, LOG_TARGET);
test_table(mac_address_policy, MAC_ADDRESS_POLICY);
test_table(managed_oom_mode, MANAGED_OOM_MODE);
test_table(managed_oom_preference, MANAGED_OOM_PREFERENCE);
test_table(manager_state, MANAGER_STATE);
test_table(manager_timestamp, MANAGER_TIMESTAMP);
test_table(mount_exec_command, MOUNT_EXEC_COMMAND);

View File

@ -1,7 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "device-util.h"
#include "alloc-util.h"
#include "device-util.h"
#include "errno-util.h"
#include "link-config.h"
#include "log.h"
#include "string-util.h"
@ -20,7 +21,7 @@ static int builtin_net_setup_link(sd_device *dev, int argc, char **argv, bool te
r = link_get_driver(ctx, dev, &driver);
if (r < 0)
log_device_full_errno(dev, r == -EOPNOTSUPP ? LOG_DEBUG : LOG_WARNING,
log_device_full_errno(dev, ERRNO_IS_NOT_SUPPORTED(r) || r == -ENODEV ? LOG_DEBUG : LOG_WARNING,
r, "Failed to query device driver: %m");
else
udev_builtin_add_property(dev, test, "ID_NET_DRIVER", driver);
@ -29,13 +30,17 @@ static int builtin_net_setup_link(sd_device *dev, int argc, char **argv, bool te
if (r < 0) {
if (r == -ENOENT)
return log_device_debug_errno(dev, r, "No matching link configuration found.");
if (r == -ENODEV)
return log_device_debug_errno(dev, r, "Link vanished while searching for configuration for it.");
return log_device_error_errno(dev, r, "Failed to get link config: %m");
}
r = link_config_apply(ctx, link, dev, &name);
if (r < 0)
log_device_warning_errno(dev, r, "Could not apply link config, ignoring: %m");
if (r == -ENODEV)
log_device_debug_errno(dev, r, "Link vanished while applying configuration, ignoring.");
else if (r < 0)
log_device_warning_errno(dev, r, "Could not apply link configuration, ignoring: %m");
udev_builtin_add_property(dev, test, "ID_NET_LINK_FILE", link->filename);

View File

@ -138,6 +138,10 @@ MakeDirectory=
Mark=
MaxConnections=
MaxConnectionsPerSource=
ManagedOOMSwap=
ManagedOOMMemoryPressure=
ManagedOOMMemoryPressureLimitPercent=
ManagedOOMPreference=
MemoryAccounting=
MemoryHigh=
MemoryLimit=

View File

@ -124,6 +124,7 @@ BASICTOOLS=(
rmdir
sed
seq
setfattr
setfont
setsid
sfdisk

View File

@ -1,35 +0,0 @@
[Match]
Name=dummy98
[Network]
IPv6AcceptRA=no
# these lines are ignored
Address=hogehoge
Address=foofoo
[Route]
Gateway=20.20.20.1
[Address]
Address=10.2.3.4/16
PreferredLifetime=0
Scope=link
[Address]
Address=2001:0db8:0:f101::1/64
[Address]
Address=20.20.20.100/24
[Address]
# this section must be ignored
Peer=hoge
Address=10.10.0.1/16
Label=30
[Address]
# this section must be ignored
Label=30
Peer=hoge
Address=10.10.0.2/16

View File

@ -52,6 +52,15 @@ Peer=2001:db8:0:f103::10/128
[Address]
Address=::/64
[Address]
Address=10.7.8.9/16
PreferredLifetime=0
Scope=link
[Address]
Address=2001:0db8:1:f101::1/64
PreferredLifetime=0
# test for ENOBUFS issue #17012
[Network]
Address=10.3.3.1/16

View File

@ -1753,7 +1753,6 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
'25-address-dad-veth99.network',
'25-address-link-section.network',
'25-address-peer-ipv4.network',
'25-address-preferred-lifetime-zero.network',
'25-address-static.network',
'25-activation-policy.network',
'25-bind-carrier.network',
@ -1830,38 +1829,40 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
output = check_output('ip -4 address show dev dummy98')
print(output)
self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
self.assertIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output)
self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output)
self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output)
self.assertIn('inet 10.7.8.9/16 brd 10.7.255.255 scope link deprecated dummy98', output)
# test for ENOBUFS issue #17012
for i in range(1,254):
self.assertRegex(output, f'inet 10.3.3.{i}/16 brd 10.3.255.255')
self.assertIn(f'inet 10.3.3.{i}/16 brd 10.3.255.255', output)
# invalid sections
self.assertNotRegex(output, '10.10.0.1/16')
self.assertNotRegex(output, '10.10.0.2/16')
self.assertNotIn('10.10.0.1/16', output)
self.assertNotIn('10.10.0.2/16', output)
output = check_output('ip -4 address show dev dummy98 label 32')
self.assertRegex(output, 'inet 10.3.2.3/16 brd 10.3.255.255 scope global 32')
self.assertIn('inet 10.3.2.3/16 brd 10.3.255.255 scope global 32', output)
output = check_output('ip -4 address show dev dummy98 label 33')
self.assertRegex(output, 'inet 10.4.2.3 peer 10.4.2.4/16 scope global 33')
self.assertIn('inet 10.4.2.3 peer 10.4.2.4/16 scope global 33', output)
output = check_output('ip -4 address show dev dummy98 label 34')
self.assertRegex(output, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
self.assertRegex(output, r'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
output = check_output('ip -4 address show dev dummy98 label 35')
self.assertRegex(output, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
self.assertRegex(output, r'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
output = check_output('ip -6 address show dev dummy98')
print(output)
self.assertRegex(output, 'inet6 2001:db8:0:f101::15/64 scope global')
self.assertRegex(output, 'inet6 2001:db8:0:f101::16/64 scope global')
self.assertRegex(output, 'inet6 2001:db8:0:f102::15/64 scope global')
self.assertRegex(output, 'inet6 2001:db8:0:f102::16/64 scope global')
self.assertRegex(output, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global')
self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global')
self.assertIn('inet6 2001:db8:0:f101::15/64 scope global', output)
self.assertIn('inet6 2001:db8:0:f101::16/64 scope global', output)
self.assertIn('inet6 2001:db8:0:f102::15/64 scope global', output)
self.assertIn('inet6 2001:db8:0:f102::16/64 scope global', output)
self.assertIn('inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global', output)
self.assertIn('inet6 2001:db8:1:f101::1/64 scope global deprecated', output)
self.assertRegex(output, r'inet6 fd[0-9a-f:]*1/64 scope global')
restart_networkd()
self.wait_online(['dummy98:routable'])
@ -1869,22 +1870,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
# test for ENOBUFS issue #17012
output = check_output('ip -4 address show dev dummy98')
for i in range(1,254):
self.assertRegex(output, f'inet 10.3.3.{i}/16 brd 10.3.255.255')
def test_address_preferred_lifetime_zero_ipv6(self):
copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero.network', '12-dummy.netdev')
start_networkd(5)
self.wait_online(['dummy98:routable'])
output = check_output('ip address show dummy98')
print(output)
self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
output = check_output('ip route show dev dummy98')
print(output)
self.assertRegex(output, 'default via 20.20.20.1 proto static')
self.assertIn(f'inet 10.3.3.{i}/16 brd 10.3.255.255', output)
def test_address_dad(self):
copy_unit_to_networkd_unit_path('25-address-dad-veth99.network', '25-address-dad-veth-peer.network',

View File

@ -0,0 +1,7 @@
[Unit]
Description=Create some memory pressure
[Service]
MemoryHigh=2M
Slice=testsuite-56-workload.slice
ExecStart=/usr/lib/systemd/tests/testdata/units/testsuite-56-slowgrowth.sh

View File

@ -13,6 +13,8 @@ if [[ "$cgroup_type" != *"cgroup2"* ]] && [[ "$cgroup_type" != *"0x63677270"* ]]
fi
[[ -e /skipped ]] && exit 0 || true
rm -rf /etc/systemd/system/testsuite-56-testbloat.service.d
echo "DefaultMemoryPressureDurationSec=5s" >> /etc/systemd/oomd.conf
systemctl start testsuite-56-testchill.service
@ -23,20 +25,47 @@ oomctl | grep "/testsuite-56-workload.slice"
oomctl | grep "1.00%"
oomctl | grep "Default Memory Pressure Duration: 5s"
# systemd-oomd watches for elevated pressure for 30 seconds before acting.
# It can take time to build up pressure so either wait 5 minutes or for the service to fail.
timeout=$(date -ud "5 minutes" +%s)
# systemd-oomd watches for elevated pressure for 5 seconds before acting.
# It can take time to build up pressure so either wait 2 minutes or for the service to fail.
timeout=$(date -ud "2 minutes" +%s)
while [[ $(date -u +%s) -le $timeout ]]; do
if ! systemctl status testsuite-56-testbloat.service; then
break
fi
sleep 15
sleep 5
done
# testbloat should be killed and testchill should be fine
if systemctl status testsuite-56-testbloat.service; then exit 42; fi
if ! systemctl status testsuite-56-testchill.service; then exit 24; fi
# only run this portion of the test if we can set xattrs
if setfattr -n user.xattr_test -v 1 /sys/fs/cgroup/; then
sleep 120 # wait for systemd-oomd kill cool down and elevated memory pressure to come down
mkdir -p /etc/systemd/system/testsuite-56-testbloat.service.d/
echo "[Service]" > /etc/systemd/system/testsuite-56-testbloat.service.d/override.conf
echo "ManagedOOMPreference=avoid" >> /etc/systemd/system/testsuite-56-testbloat.service.d/override.conf
systemctl daemon-reload
systemctl start testsuite-56-testchill.service
systemctl start testsuite-56-testmunch.service
systemctl start testsuite-56-testbloat.service
timeout=$(date -ud "2 minutes" +%s)
while [[ $(date -u +%s) -le $timeout ]]; do
if ! systemctl status testsuite-56-testmunch.service; then
break
fi
sleep 5
done
# testmunch should be killed since testbloat had the avoid xattr on it
if ! systemctl status testsuite-56-testbloat.service; then exit 25; fi
if systemctl status testsuite-56-testmunch.service; then exit 43; fi
if ! systemctl status testsuite-56-testchill.service; then exit 24; fi
fi
systemd-analyze log-level info
echo OK > /testok