summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2020-11-11 14:11:02 +0100
committerGitHub <noreply@github.com>2020-11-11 14:11:02 +0100
commit23dce98e89616092007005692a4574ab908db5a6 (patch)
tree829c00842440ba9fb8c42d765b25b341860ba45c
parentNEWS,man: tweak the description of FixedRandomDelay= (diff)
parentuser: move "extrinsic" units to their root slice (diff)
downloadsystemd-23dce98e89616092007005692a4574ab908db5a6.tar.xz
systemd-23dce98e89616092007005692a4574ab908db5a6.zip
Merge pull request #16603 from benzea/benzea/special-app-slice
Use app.slice by default in user manager (and define special user slices)
-rw-r--r--man/systemd.special.xml54
-rw-r--r--src/basic/special.h5
-rw-r--r--src/core/mount.c13
-rw-r--r--src/core/swap.c59
-rw-r--r--src/core/unit.c21
-rw-r--r--src/core/unit.h8
-rw-r--r--units/user/app.slice12
-rw-r--r--units/user/background.slice12
-rw-r--r--units/user/meson.build3
-rw-r--r--units/user/session.slice12
-rw-r--r--units/user/systemd-exit.service4
-rw-r--r--units/user/systemd-tmpfiles-clean.service1
12 files changed, 166 insertions, 38 deletions
diff --git a/man/systemd.special.xml b/man/systemd.special.xml
index d9439c23ded..a70e9ee0cae 100644
--- a/man/systemd.special.xml
+++ b/man/systemd.special.xml
@@ -1179,6 +1179,60 @@
</varlistentry>
</variablelist>
</refsect2>
+
+ <refsect2>
+ <title>Special User Slice Units</title>
+
+ <para>There are four <literal>.slice</literal> units which form the basis of the user hierarchy for
+ assignment of resources for user applications and services. See
+ <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ for details about slice units and the documentation about
+ <ulink url="https://systemd.io/DESKTOP_ENVIRONMENTS">Desktop Environments</ulink>
+ for further information.</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><filename>-.slice</filename></term>
+ <listitem>
+ <para>The root slice is the root of the user's slice hierarchy.
+ It usually does not contain units directly, but may be used to set defaults for the whole tree.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><filename>app.slice</filename></term>
+ <listitem>
+ <para>By default, all user services and applications managed by
+ <command>systemd</command> are found in this slice.
+ All interactively launched applications like web browsers and text editors
+ as well as non-critical services should be placed into this slice.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><filename>session.slice</filename></term>
+ <listitem>
+ <para>All essential services and applications required for the
+ session should use this slice.
+ These are services that either cannot be restarted easily
+ or where latency issues may affect the interactivity of the system and applications.
+ This includes the display server, screen readers and other services such as DBus or XDG portals.
+ Such services should be configured to be part of this slice by
+ adding <varname>Slice=session.slice</varname> to their unit files.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><filename>background.slice</filename></term>
+ <listitem>
+ <para>All services running low-priority background tasks should use this slice.
+ This permits resources to be preferentially assigned to the other slices.
+ Examples include non-interactive tasks like file indexing or backup operations
+ where latency is not important.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect2>
</refsect1>
<refsect1>
diff --git a/src/basic/special.h b/src/basic/special.h
index b602bb097cb..d55b3289dee 100644
--- a/src/basic/special.h
+++ b/src/basic/special.h
@@ -107,3 +107,8 @@
/* The root directory. */
#define SPECIAL_ROOT_MOUNT "-.mount"
+
+/* Special slices valid for the user instance */
+#define SPECIAL_SESSION_SLICE "session.slice"
+#define SPECIAL_APP_SLICE "app.slice"
+#define SPECIAL_BACKGROUND_SLICE "background.slice"
diff --git a/src/core/mount.c b/src/core/mount.c
index c96c137d297..41dc7e99674 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -412,8 +412,9 @@ static int mount_add_quota_dependencies(Mount *m) {
return 0;
}
-static bool mount_is_extrinsic(Mount *m) {
+static bool mount_is_extrinsic(Unit *u) {
MountParameters *p;
+ Mount *m = MOUNT(u);
assert(m);
/* Returns true for all units that are "magic" and should be excluded from the usual
@@ -422,10 +423,7 @@ static bool mount_is_extrinsic(Mount *m) {
* ourselves but it's fine if the user operates on them with us. */
/* We only automatically manage mounts if we are in system mode */
- if (!MANAGER_IS_SYSTEM(UNIT(m)->manager))
- return true;
-
- if (UNIT(m)->perpetual) /* All perpetual units never change state */
+ if (MANAGER_IS_USER(u->manager))
return true;
p = get_mount_parameters(m);
@@ -493,7 +491,7 @@ static int mount_add_default_dependencies(Mount *m) {
* guaranteed to stay mounted the whole time, since our system is on it. Also, don't
* bother with anything mounted below virtual file systems, it's also going to be virtual,
* and hence not worth the effort. */
- if (mount_is_extrinsic(m))
+ if (mount_is_extrinsic(UNIT(m)))
return 0;
p = get_mount_parameters(m);
@@ -790,7 +788,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
prefix, p ? strna(p->options) : "n/a",
prefix, yes_no(m->from_proc_self_mountinfo),
prefix, yes_no(m->from_fragment),
- prefix, yes_no(mount_is_extrinsic(m)),
+ prefix, yes_no(mount_is_extrinsic(u)),
prefix, m->directory_mode,
prefix, yes_no(m->sloppy_options),
prefix, yes_no(m->lazy_unmount),
@@ -2161,6 +2159,7 @@ const UnitVTable mount_vtable = {
.will_restart = unit_will_restart_default,
.may_gc = mount_may_gc,
+ .is_extrinsic = mount_is_extrinsic,
.sigchld_event = mount_sigchld_event,
diff --git a/src/core/swap.c b/src/core/swap.c
index d984ac0f2d0..76e491ad94f 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -56,6 +56,35 @@ static bool SWAP_STATE_WITH_PROCESS(SwapState state) {
SWAP_CLEANING);
}
+_pure_ static UnitActiveState swap_active_state(Unit *u) {
+ assert(u);
+
+ return state_translation_table[SWAP(u)->state];
+}
+
+_pure_ static const char *swap_sub_state_to_string(Unit *u) {
+ assert(u);
+
+ return swap_state_to_string(SWAP(u)->state);
+}
+
+_pure_ static bool swap_may_gc(Unit *u) {
+ Swap *s = SWAP(u);
+
+ assert(s);
+
+ if (s->from_proc_swaps)
+ return false;
+
+ return true;
+}
+
+_pure_ static bool swap_is_extrinsic(Unit *u) {
+ assert(SWAP(u));
+
+ return MANAGER_IS_USER(u->manager);
+}
+
static void swap_unset_proc_swaps(Swap *s) {
assert(s);
@@ -610,13 +639,15 @@ static void swap_dump(Unit *u, FILE *f, const char *prefix) {
"%sClean Result: %s\n"
"%sWhat: %s\n"
"%sFrom /proc/swaps: %s\n"
- "%sFrom fragment: %s\n",
+ "%sFrom fragment: %s\n"
+ "%sExtrinsic: %s\n",
prefix, swap_state_to_string(s->state),
prefix, swap_result_to_string(s->result),
prefix, swap_result_to_string(s->clean_result),
prefix, s->what,
prefix, yes_no(s->from_proc_swaps),
- prefix, yes_no(s->from_fragment));
+ prefix, yes_no(s->from_fragment),
+ prefix, yes_no(swap_is_extrinsic(u)));
if (s->devnode)
fprintf(f, "%sDevice Node: %s\n", prefix, s->devnode);
@@ -1028,29 +1059,6 @@ static int swap_deserialize_item(Unit *u, const char *key, const char *value, FD
return 0;
}
-_pure_ static UnitActiveState swap_active_state(Unit *u) {
- assert(u);
-
- return state_translation_table[SWAP(u)->state];
-}
-
-_pure_ static const char *swap_sub_state_to_string(Unit *u) {
- assert(u);
-
- return swap_state_to_string(SWAP(u)->state);
-}
-
-_pure_ static bool swap_may_gc(Unit *u) {
- Swap *s = SWAP(u);
-
- assert(s);
-
- if (s->from_proc_swaps)
- return false;
-
- return true;
-}
-
static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
Swap *s = SWAP(u);
SwapResult f;
@@ -1649,6 +1657,7 @@ const UnitVTable swap_vtable = {
.will_restart = unit_will_restart_default,
.may_gc = swap_may_gc,
+ .is_extrinsic = swap_is_extrinsic,
.sigchld_event = swap_sigchld_event,
diff --git a/src/core/unit.c b/src/core/unit.c
index 1d9691fb57d..45a417a0906 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1988,6 +1988,10 @@ int unit_stop(Unit *u) {
bool unit_can_stop(Unit *u) {
assert(u);
+ /* Note: if we return true here, it does not mean that the unit may be successfully stopped.
+ * Extrinsic units follow external state and they may stop following external state changes
+ * (hence we return true here), but an attempt to do this through the manager will fail. */
+
if (!unit_type_supported(u->type))
return false;
@@ -3345,12 +3349,17 @@ int unit_set_default_slice(Unit *u) {
if (MANAGER_IS_SYSTEM(u->manager))
slice_name = strjoina("system-", escaped, ".slice");
else
- slice_name = strjoina(escaped, ".slice");
- } else
- slice_name =
- MANAGER_IS_SYSTEM(u->manager) && !unit_has_name(u, SPECIAL_INIT_SCOPE)
- ? SPECIAL_SYSTEM_SLICE
- : SPECIAL_ROOT_SLICE;
+ slice_name = strjoina("app-", escaped, ".slice");
+
+ } else if (unit_is_extrinsic(u))
+ /* Keep all extrinsic units (e.g. perpetual units and swap and mount units in user mode) in
+ * the root slice. They don't really belong in one of the subslices. */
+ slice_name = SPECIAL_ROOT_SLICE;
+
+ else if (MANAGER_IS_SYSTEM(u->manager))
+ slice_name = SPECIAL_SYSTEM_SLICE;
+ else
+ slice_name = SPECIAL_APP_SLICE;
r = manager_load_unit(u->manager, slice_name, NULL, NULL, &slice);
if (r < 0)
diff --git a/src/core/unit.h b/src/core/unit.h
index 8cb71357231..02b2b24206f 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -531,6 +531,9 @@ typedef struct UnitVTable {
* even though nothing references it and it isn't active in any way. */
bool (*may_gc)(Unit *u);
+ /* Return true when the unit is not controlled by the manager (e.g. extrinsic mounts). */
+ bool (*is_extrinsic)(Unit *u);
+
/* When the unit is not running and no job for it queued we shall release its runtime resources */
void (*release_resources)(Unit *u);
@@ -684,6 +687,11 @@ int unit_set_description(Unit *u, const char *description);
bool unit_may_gc(Unit *u);
+static inline bool unit_is_extrinsic(Unit *u) {
+ return u->perpetual ||
+ (UNIT_VTABLE(u)->is_extrinsic && UNIT_VTABLE(u)->is_extrinsic(u));
+}
+
void unit_add_to_load_queue(Unit *u);
void unit_add_to_dbus_queue(Unit *u);
void unit_add_to_cleanup_queue(Unit *u);
diff --git a/units/user/app.slice b/units/user/app.slice
new file mode 100644
index 00000000000..065ea77e96c
--- /dev/null
+++ b/units/user/app.slice
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=User Application Slice
+Documentation=man:systemd.special(7)
diff --git a/units/user/background.slice b/units/user/background.slice
new file mode 100644
index 00000000000..03c89b66be5
--- /dev/null
+++ b/units/user/background.slice
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=User Background Tasks Slice
+Documentation=man:systemd.special(7)
diff --git a/units/user/meson.build b/units/user/meson.build
index b2a599b6d8a..337a92092db 100644
--- a/units/user/meson.build
+++ b/units/user/meson.build
@@ -1,6 +1,8 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
units = [
+ 'app.slice',
+ 'background.slice',
'basic.target',
'bluetooth.target',
'default.target',
@@ -9,6 +11,7 @@ units = [
'graphical-session.target',
'paths.target',
'printer.target',
+ 'session.slice',
'shutdown.target',
'smartcard.target',
'sockets.target',
diff --git a/units/user/session.slice b/units/user/session.slice
new file mode 100644
index 00000000000..e0b38c5e32d
--- /dev/null
+++ b/units/user/session.slice
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=User Core Session Slice
+Documentation=man:systemd.special(7)
diff --git a/units/user/systemd-exit.service b/units/user/systemd-exit.service
index 91953e0524d..18725253bb3 100644
--- a/units/user/systemd-exit.service
+++ b/units/user/systemd-exit.service
@@ -14,3 +14,7 @@ DefaultDependencies=no
Requires=shutdown.target
After=shutdown.target
SuccessAction=exit-force
+
+[Service]
+# Place into the root slice to not keep another slice unit alive
+Slice=-.slice
diff --git a/units/user/systemd-tmpfiles-clean.service b/units/user/systemd-tmpfiles-clean.service
index ff319d2b3a9..6a937071f76 100644
--- a/units/user/systemd-tmpfiles-clean.service
+++ b/units/user/systemd-tmpfiles-clean.service
@@ -19,3 +19,4 @@ Type=oneshot
ExecStart=systemd-tmpfiles --user --clean
SuccessExitStatus=DATAERR
IOSchedulingClass=idle
+Slice=background.slice