mirror of
https://github.com/systemd/systemd.git
synced 2025-03-23 10:50:16 +03:00
Merge pull request #16603 from benzea/benzea/special-app-slice
Use app.slice by default in user manager (and define special user slices)
This commit is contained in:
commit
23dce98e89
@ -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>
|
||||
|
@ -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"
|
||||
|
@ -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,
|
||||
|
||||
|
@ -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,
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
12
units/user/app.slice
Normal file
12
units/user/app.slice
Normal file
@ -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)
|
12
units/user/background.slice
Normal file
12
units/user/background.slice
Normal file
@ -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)
|
@ -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',
|
||||
|
12
units/user/session.slice
Normal file
12
units/user/session.slice
Normal file
@ -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)
|
@ -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
|
||||
|
@ -19,3 +19,4 @@ Type=oneshot
|
||||
ExecStart=systemd-tmpfiles --user --clean
|
||||
SuccessExitStatus=DATAERR
|
||||
IOSchedulingClass=idle
|
||||
Slice=background.slice
|
||||
|
Loading…
x
Reference in New Issue
Block a user