2020-11-09 05:23:58 +01:00
|
|
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
2013-06-17 21:33:26 +02:00
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
#include "alloc-util.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "dbus-slice.h"
|
2018-11-27 20:15:45 +01:00
|
|
|
#include "dbus-unit.h"
|
2020-04-29 17:53:43 +02:00
|
|
|
#include "fd-util.h"
|
2013-06-17 21:33:26 +02:00
|
|
|
#include "log.h"
|
2018-10-17 20:40:09 +02:00
|
|
|
#include "serialize.h"
|
2015-11-16 22:09:36 +01:00
|
|
|
#include "slice.h"
|
2013-06-17 21:33:26 +02:00
|
|
|
#include "special.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "string-util.h"
|
|
|
|
#include "strv.h"
|
2013-06-17 21:33:26 +02:00
|
|
|
#include "unit-name.h"
|
core: unified cgroup hierarchy support
This patch set adds full support the new unified cgroup hierarchy logic
of modern kernels.
A new kernel command line option "systemd.unified_cgroup_hierarchy=1" is
added. If specified the unified hierarchy is mounted to /sys/fs/cgroup
instead of a tmpfs. No further hierarchies are mounted. The kernel
command line option defaults to off. We can turn it on by default as
soon as the kernel's APIs regarding this are stabilized (but even then
downstream distros might want to turn this off, as this will break any
tools that access cgroupfs directly).
It is possibly to choose for each boot individually whether the unified
or the legacy hierarchy is used. nspawn will by default provide the
legacy hierarchy to containers if the host is using it, and the unified
otherwise. However it is possible to run containers with the unified
hierarchy on a legacy host and vice versa, by setting the
$UNIFIED_CGROUP_HIERARCHY environment variable for nspawn to 1 or 0,
respectively.
The unified hierarchy provides reliable cgroup empty notifications for
the first time, via inotify. To make use of this we maintain one
manager-wide inotify fd, and each cgroup to it.
This patch also removes cg_delete() which is unused now.
On kernel 4.2 only the "memory" controller is compatible with the
unified hierarchy, hence that's the only controller systemd exposes when
booted in unified heirarchy mode.
This introduces a new enum for enumerating supported controllers, plus a
related enum for the mask bits mapping to it. The core is changed to
make use of this everywhere.
This moves PID 1 into a new "init.scope" implicit scope unit in the root
slice. This is necessary since on the unified hierarchy cgroups may
either contain subgroups or processes but not both. PID 1 hence has to
move out of the root cgroup (strictly speaking the root cgroup is the
only one where processes and subgroups are still allowed, but in order
to support containers nicey, we move PID 1 into the new scope in all
cases.) This new unit is also used on legacy hierarchy setups. It's
actually pretty useful on all systems, as it can then be used to filter
journal messages coming from PID 1, and so on.
The root slice ("-.slice") is now implicitly created and started (and
does not require a unit file on disk anymore), since
that's where "init.scope" is located and the slice needs to be started
before the scope can.
To check whether we are in unified or legacy hierarchy mode we use
statfs() on /sys/fs/cgroup. If the .f_type field reports tmpfs we are in
legacy mode, if it reports cgroupfs we are in unified mode.
This patch set carefuly makes sure that cgls and cgtop continue to work
as desired.
When invoking nspawn as a service it will implicitly create two
subcgroups in the cgroup it is using, one to move the nspawn process
into, the other to move the actual container processes into. This is
done because of the requirement that cgroups may either contain
processes or other subgroups.
2015-09-01 19:22:36 +02:00
|
|
|
#include "unit.h"
|
2013-06-17 21:33:26 +02:00
|
|
|
|
|
|
|
static const UnitActiveState state_translation_table[_SLICE_STATE_MAX] = {
|
|
|
|
[SLICE_DEAD] = UNIT_INACTIVE,
|
|
|
|
[SLICE_ACTIVE] = UNIT_ACTIVE
|
|
|
|
};
|
|
|
|
|
2016-02-18 22:51:23 +01:00
|
|
|
static void slice_init(Unit *u) {
|
|
|
|
assert(u);
|
|
|
|
assert(u->load_state == UNIT_STUB);
|
|
|
|
|
|
|
|
u->ignore_on_isolate = true;
|
|
|
|
}
|
|
|
|
|
2013-06-17 21:33:26 +02:00
|
|
|
static void slice_set_state(Slice *t, SliceState state) {
|
|
|
|
SliceState old_state;
|
|
|
|
assert(t);
|
|
|
|
|
2018-11-27 20:15:45 +01:00
|
|
|
if (t->state != state)
|
|
|
|
bus_unit_send_pending_change_signal(UNIT(t), false);
|
|
|
|
|
2013-06-17 21:33:26 +02:00
|
|
|
old_state = t->state;
|
|
|
|
t->state = state;
|
|
|
|
|
|
|
|
if (state != old_state)
|
|
|
|
log_debug("%s changed %s -> %s",
|
|
|
|
UNIT(t)->id,
|
|
|
|
slice_state_to_string(old_state),
|
|
|
|
slice_state_to_string(state));
|
|
|
|
|
2018-06-01 19:06:19 +02:00
|
|
|
unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], 0);
|
2013-06-17 21:33:26 +02:00
|
|
|
}
|
|
|
|
|
2013-06-27 04:14:27 +02:00
|
|
|
static int slice_add_parent_slice(Slice *s) {
|
2017-12-07 14:23:58 +01:00
|
|
|
Unit *u = UNIT(s), *parent;
|
|
|
|
_cleanup_free_ char *a = NULL;
|
2013-06-27 04:14:27 +02:00
|
|
|
int r;
|
2013-06-17 21:33:26 +02:00
|
|
|
|
|
|
|
assert(s);
|
|
|
|
|
2017-12-07 14:23:58 +01:00
|
|
|
if (UNIT_ISSET(u->slice))
|
2013-06-17 21:33:26 +02:00
|
|
|
return 0;
|
|
|
|
|
2017-12-07 14:23:58 +01:00
|
|
|
r = slice_build_parent_slice(u->id, &a);
|
|
|
|
if (r <= 0) /* 0 means root slice */
|
|
|
|
return r;
|
2013-06-17 21:33:26 +02:00
|
|
|
|
2017-12-07 14:23:58 +01:00
|
|
|
r = manager_load_unit(u->manager, a, NULL, NULL, &parent);
|
2013-06-17 21:33:26 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2018-02-13 13:12:43 +01:00
|
|
|
unit_ref_set(&u->slice, u, parent);
|
2013-06-17 21:33:26 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int slice_add_default_dependencies(Slice *s) {
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(s);
|
|
|
|
|
2015-11-11 20:42:39 +01:00
|
|
|
if (!UNIT(s)->default_dependencies)
|
|
|
|
return 0;
|
|
|
|
|
2013-06-17 21:33:26 +02:00
|
|
|
/* Make sure slices are unloaded on shutdown */
|
2013-07-01 00:03:57 +02:00
|
|
|
r = unit_add_two_dependencies_by_name(
|
|
|
|
UNIT(s),
|
|
|
|
UNIT_BEFORE, UNIT_CONFLICTS,
|
2018-09-15 20:02:00 +02:00
|
|
|
SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
|
2013-06-17 21:33:26 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int slice_verify(Slice *s) {
|
2015-05-05 22:39:14 +02:00
|
|
|
_cleanup_free_ char *parent = NULL;
|
|
|
|
int r;
|
|
|
|
|
2013-06-17 21:33:26 +02:00
|
|
|
assert(s);
|
2019-10-11 12:48:33 +02:00
|
|
|
assert(UNIT(s)->load_state == UNIT_LOADED);
|
2013-06-17 21:33:26 +02:00
|
|
|
|
2020-11-26 01:27:21 +01:00
|
|
|
if (!slice_name_is_valid(UNIT(s)->id))
|
|
|
|
return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(ENOEXEC), "Slice name %s is not valid. Refusing.", UNIT(s)->id);
|
2015-05-05 22:39:14 +02:00
|
|
|
|
|
|
|
r = slice_build_parent_slice(UNIT(s)->id, &parent);
|
|
|
|
if (r < 0)
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
return log_unit_error_errno(UNIT(s), r, "Failed to determine parent slice: %m");
|
2015-05-05 22:39:14 +02:00
|
|
|
|
2020-11-26 01:27:21 +01:00
|
|
|
if (parent ? !unit_has_name(UNIT_DEREF(UNIT(s)->slice), parent) : UNIT_ISSET(UNIT(s)->slice))
|
|
|
|
return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(ENOEXEC), "Located outside of parent slice. Refusing.");
|
2013-06-17 21:33:26 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-10-24 20:37:54 +02:00
|
|
|
static int slice_load_root_slice(Unit *u) {
|
|
|
|
assert(u);
|
|
|
|
|
|
|
|
if (!unit_has_name(u, SPECIAL_ROOT_SLICE))
|
|
|
|
return 0;
|
|
|
|
|
2016-10-24 21:41:54 +02:00
|
|
|
u->perpetual = true;
|
2016-10-24 20:37:54 +02:00
|
|
|
|
|
|
|
/* The root slice is a bit special. For example it is always running and cannot be terminated. Because of its
|
|
|
|
* special semantics we synthesize it here, instead of relying on the unit file on disk. */
|
|
|
|
|
|
|
|
u->default_dependencies = false;
|
|
|
|
|
|
|
|
if (!u->description)
|
|
|
|
u->description = strdup("Root Slice");
|
|
|
|
if (!u->documentation)
|
2018-10-31 17:03:50 +01:00
|
|
|
u->documentation = strv_new("man:systemd.special(7)");
|
2016-10-24 20:37:54 +02:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-02-04 21:46:27 +01:00
|
|
|
static int slice_load_system_slice(Unit *u) {
|
|
|
|
assert(u);
|
|
|
|
|
|
|
|
if (!MANAGER_IS_SYSTEM(u->manager))
|
|
|
|
return 0;
|
|
|
|
if (!unit_has_name(u, SPECIAL_SYSTEM_SLICE))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
u->perpetual = true;
|
|
|
|
|
|
|
|
/* The system slice is a bit special. For example it is always running and cannot be terminated. Because of its
|
|
|
|
* special semantics we synthesize it here, instead of relying on the unit file on disk. */
|
|
|
|
|
|
|
|
u->default_dependencies = false;
|
|
|
|
|
|
|
|
if (!u->description)
|
|
|
|
u->description = strdup("System Slice");
|
|
|
|
if (!u->documentation)
|
2018-10-31 17:03:50 +01:00
|
|
|
u->documentation = strv_new("man:systemd.special(7)");
|
2018-02-04 21:46:27 +01:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2013-06-17 21:33:26 +02:00
|
|
|
static int slice_load(Unit *u) {
|
|
|
|
Slice *s = SLICE(u);
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(s);
|
2016-04-07 15:43:59 +02:00
|
|
|
assert(u->load_state == UNIT_STUB);
|
2013-06-17 21:33:26 +02:00
|
|
|
|
2016-10-24 20:37:54 +02:00
|
|
|
r = slice_load_root_slice(u);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2018-02-04 21:46:27 +01:00
|
|
|
r = slice_load_system_slice(u);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2019-10-11 10:41:44 +02:00
|
|
|
r = unit_load_fragment_and_dropin(u, false);
|
2013-06-17 21:33:26 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2019-10-11 12:48:33 +02:00
|
|
|
if (u->load_state != UNIT_LOADED)
|
|
|
|
return 0;
|
2013-06-17 21:33:26 +02:00
|
|
|
|
2019-10-11 12:48:33 +02:00
|
|
|
/* This is a new unit? Then let's add in some extras */
|
|
|
|
r = unit_patch_contexts(u);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2014-03-19 20:40:05 +01:00
|
|
|
|
2019-10-11 12:48:33 +02:00
|
|
|
r = slice_add_parent_slice(s);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-17 21:33:26 +02:00
|
|
|
|
2019-10-11 12:48:33 +02:00
|
|
|
r = slice_add_default_dependencies(s);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-17 21:33:26 +02:00
|
|
|
|
|
|
|
return slice_verify(s);
|
|
|
|
}
|
|
|
|
|
2015-04-24 15:27:19 +02:00
|
|
|
static int slice_coldplug(Unit *u) {
|
2013-06-17 21:33:26 +02:00
|
|
|
Slice *t = SLICE(u);
|
|
|
|
|
|
|
|
assert(t);
|
|
|
|
assert(t->state == SLICE_DEAD);
|
|
|
|
|
|
|
|
if (t->deserialized_state != t->state)
|
|
|
|
slice_set_state(t, t->deserialized_state);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void slice_dump(Unit *u, FILE *f, const char *prefix) {
|
|
|
|
Slice *t = SLICE(u);
|
|
|
|
|
|
|
|
assert(t);
|
|
|
|
assert(f);
|
|
|
|
|
|
|
|
fprintf(f,
|
|
|
|
"%sSlice State: %s\n",
|
|
|
|
prefix, slice_state_to_string(t->state));
|
2013-06-27 04:14:27 +02:00
|
|
|
|
2019-10-03 14:21:29 +02:00
|
|
|
cgroup_context_dump(UNIT(t), f, prefix);
|
2013-06-17 21:33:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static int slice_start(Unit *u) {
|
|
|
|
Slice *t = SLICE(u);
|
2016-08-30 23:18:46 +02:00
|
|
|
int r;
|
2013-06-17 21:33:26 +02:00
|
|
|
|
|
|
|
assert(t);
|
|
|
|
assert(t->state == SLICE_DEAD);
|
|
|
|
|
2016-08-30 23:18:46 +02:00
|
|
|
r = unit_acquire_invocation_id(u);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2015-03-01 16:24:19 +01:00
|
|
|
(void) unit_realize_cgroup(u);
|
2019-03-22 11:25:49 +01:00
|
|
|
(void) unit_reset_accounting(u);
|
2013-06-17 21:33:26 +02:00
|
|
|
|
|
|
|
slice_set_state(t, SLICE_ACTIVE);
|
2015-01-28 15:07:13 +01:00
|
|
|
return 1;
|
2013-06-17 21:33:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static int slice_stop(Unit *u) {
|
|
|
|
Slice *t = SLICE(u);
|
|
|
|
|
|
|
|
assert(t);
|
|
|
|
assert(t->state == SLICE_ACTIVE);
|
|
|
|
|
2013-06-27 04:14:27 +02:00
|
|
|
/* We do not need to destroy the cgroup explicitly,
|
|
|
|
* unit_notify() will do that for us anyway. */
|
2013-06-17 21:33:26 +02:00
|
|
|
|
|
|
|
slice_set_state(t, SLICE_DEAD);
|
2015-01-28 15:07:13 +01:00
|
|
|
return 1;
|
2013-06-17 21:33:26 +02:00
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static int slice_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
|
2013-06-17 21:33:26 +02:00
|
|
|
return unit_kill_common(u, who, signo, -1, -1, error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int slice_serialize(Unit *u, FILE *f, FDSet *fds) {
|
|
|
|
Slice *s = SLICE(u);
|
|
|
|
|
|
|
|
assert(s);
|
|
|
|
assert(f);
|
|
|
|
assert(fds);
|
|
|
|
|
2018-10-17 20:40:09 +02:00
|
|
|
(void) serialize_item(f, "state", slice_state_to_string(s->state));
|
|
|
|
|
2013-06-17 21:33:26 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int slice_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
|
|
|
|
Slice *s = SLICE(u);
|
|
|
|
|
|
|
|
assert(u);
|
|
|
|
assert(key);
|
|
|
|
assert(value);
|
|
|
|
assert(fds);
|
|
|
|
|
|
|
|
if (streq(key, "state")) {
|
|
|
|
SliceState state;
|
|
|
|
|
|
|
|
state = slice_state_from_string(value);
|
|
|
|
if (state < 0)
|
|
|
|
log_debug("Failed to parse state value %s", value);
|
|
|
|
else
|
|
|
|
s->deserialized_state = state;
|
|
|
|
|
|
|
|
} else
|
|
|
|
log_debug("Unknown serialization key '%s'", key);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
_pure_ static UnitActiveState slice_active_state(Unit *u) {
|
|
|
|
assert(u);
|
|
|
|
|
|
|
|
return state_translation_table[SLICE(u)->state];
|
|
|
|
}
|
|
|
|
|
|
|
|
_pure_ static const char *slice_sub_state_to_string(Unit *u) {
|
|
|
|
assert(u);
|
|
|
|
|
|
|
|
return slice_state_to_string(SLICE(u)->state);
|
|
|
|
}
|
|
|
|
|
2018-02-09 19:07:01 +01:00
|
|
|
static int slice_make_perpetual(Manager *m, const char *name, Unit **ret) {
|
core: unified cgroup hierarchy support
This patch set adds full support the new unified cgroup hierarchy logic
of modern kernels.
A new kernel command line option "systemd.unified_cgroup_hierarchy=1" is
added. If specified the unified hierarchy is mounted to /sys/fs/cgroup
instead of a tmpfs. No further hierarchies are mounted. The kernel
command line option defaults to off. We can turn it on by default as
soon as the kernel's APIs regarding this are stabilized (but even then
downstream distros might want to turn this off, as this will break any
tools that access cgroupfs directly).
It is possibly to choose for each boot individually whether the unified
or the legacy hierarchy is used. nspawn will by default provide the
legacy hierarchy to containers if the host is using it, and the unified
otherwise. However it is possible to run containers with the unified
hierarchy on a legacy host and vice versa, by setting the
$UNIFIED_CGROUP_HIERARCHY environment variable for nspawn to 1 or 0,
respectively.
The unified hierarchy provides reliable cgroup empty notifications for
the first time, via inotify. To make use of this we maintain one
manager-wide inotify fd, and each cgroup to it.
This patch also removes cg_delete() which is unused now.
On kernel 4.2 only the "memory" controller is compatible with the
unified hierarchy, hence that's the only controller systemd exposes when
booted in unified heirarchy mode.
This introduces a new enum for enumerating supported controllers, plus a
related enum for the mask bits mapping to it. The core is changed to
make use of this everywhere.
This moves PID 1 into a new "init.scope" implicit scope unit in the root
slice. This is necessary since on the unified hierarchy cgroups may
either contain subgroups or processes but not both. PID 1 hence has to
move out of the root cgroup (strictly speaking the root cgroup is the
only one where processes and subgroups are still allowed, but in order
to support containers nicey, we move PID 1 into the new scope in all
cases.) This new unit is also used on legacy hierarchy setups. It's
actually pretty useful on all systems, as it can then be used to filter
journal messages coming from PID 1, and so on.
The root slice ("-.slice") is now implicitly created and started (and
does not require a unit file on disk anymore), since
that's where "init.scope" is located and the slice needs to be started
before the scope can.
To check whether we are in unified or legacy hierarchy mode we use
statfs() on /sys/fs/cgroup. If the .f_type field reports tmpfs we are in
legacy mode, if it reports cgroupfs we are in unified mode.
This patch set carefuly makes sure that cgls and cgtop continue to work
as desired.
When invoking nspawn as a service it will implicitly create two
subcgroups in the cgroup it is using, one to move the nspawn process
into, the other to move the actual container processes into. This is
done because of the requirement that cgroups may either contain
processes or other subgroups.
2015-09-01 19:22:36 +02:00
|
|
|
Unit *u;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(m);
|
2018-02-09 19:07:01 +01:00
|
|
|
assert(name);
|
core: unified cgroup hierarchy support
This patch set adds full support the new unified cgroup hierarchy logic
of modern kernels.
A new kernel command line option "systemd.unified_cgroup_hierarchy=1" is
added. If specified the unified hierarchy is mounted to /sys/fs/cgroup
instead of a tmpfs. No further hierarchies are mounted. The kernel
command line option defaults to off. We can turn it on by default as
soon as the kernel's APIs regarding this are stabilized (but even then
downstream distros might want to turn this off, as this will break any
tools that access cgroupfs directly).
It is possibly to choose for each boot individually whether the unified
or the legacy hierarchy is used. nspawn will by default provide the
legacy hierarchy to containers if the host is using it, and the unified
otherwise. However it is possible to run containers with the unified
hierarchy on a legacy host and vice versa, by setting the
$UNIFIED_CGROUP_HIERARCHY environment variable for nspawn to 1 or 0,
respectively.
The unified hierarchy provides reliable cgroup empty notifications for
the first time, via inotify. To make use of this we maintain one
manager-wide inotify fd, and each cgroup to it.
This patch also removes cg_delete() which is unused now.
On kernel 4.2 only the "memory" controller is compatible with the
unified hierarchy, hence that's the only controller systemd exposes when
booted in unified heirarchy mode.
This introduces a new enum for enumerating supported controllers, plus a
related enum for the mask bits mapping to it. The core is changed to
make use of this everywhere.
This moves PID 1 into a new "init.scope" implicit scope unit in the root
slice. This is necessary since on the unified hierarchy cgroups may
either contain subgroups or processes but not both. PID 1 hence has to
move out of the root cgroup (strictly speaking the root cgroup is the
only one where processes and subgroups are still allowed, but in order
to support containers nicey, we move PID 1 into the new scope in all
cases.) This new unit is also used on legacy hierarchy setups. It's
actually pretty useful on all systems, as it can then be used to filter
journal messages coming from PID 1, and so on.
The root slice ("-.slice") is now implicitly created and started (and
does not require a unit file on disk anymore), since
that's where "init.scope" is located and the slice needs to be started
before the scope can.
To check whether we are in unified or legacy hierarchy mode we use
statfs() on /sys/fs/cgroup. If the .f_type field reports tmpfs we are in
legacy mode, if it reports cgroupfs we are in unified mode.
This patch set carefuly makes sure that cgls and cgtop continue to work
as desired.
When invoking nspawn as a service it will implicitly create two
subcgroups in the cgroup it is using, one to move the nspawn process
into, the other to move the actual container processes into. This is
done because of the requirement that cgroups may either contain
processes or other subgroups.
2015-09-01 19:22:36 +02:00
|
|
|
|
2018-02-04 21:46:27 +01:00
|
|
|
u = manager_get_unit(m, name);
|
core: unified cgroup hierarchy support
This patch set adds full support the new unified cgroup hierarchy logic
of modern kernels.
A new kernel command line option "systemd.unified_cgroup_hierarchy=1" is
added. If specified the unified hierarchy is mounted to /sys/fs/cgroup
instead of a tmpfs. No further hierarchies are mounted. The kernel
command line option defaults to off. We can turn it on by default as
soon as the kernel's APIs regarding this are stabilized (but even then
downstream distros might want to turn this off, as this will break any
tools that access cgroupfs directly).
It is possibly to choose for each boot individually whether the unified
or the legacy hierarchy is used. nspawn will by default provide the
legacy hierarchy to containers if the host is using it, and the unified
otherwise. However it is possible to run containers with the unified
hierarchy on a legacy host and vice versa, by setting the
$UNIFIED_CGROUP_HIERARCHY environment variable for nspawn to 1 or 0,
respectively.
The unified hierarchy provides reliable cgroup empty notifications for
the first time, via inotify. To make use of this we maintain one
manager-wide inotify fd, and each cgroup to it.
This patch also removes cg_delete() which is unused now.
On kernel 4.2 only the "memory" controller is compatible with the
unified hierarchy, hence that's the only controller systemd exposes when
booted in unified heirarchy mode.
This introduces a new enum for enumerating supported controllers, plus a
related enum for the mask bits mapping to it. The core is changed to
make use of this everywhere.
This moves PID 1 into a new "init.scope" implicit scope unit in the root
slice. This is necessary since on the unified hierarchy cgroups may
either contain subgroups or processes but not both. PID 1 hence has to
move out of the root cgroup (strictly speaking the root cgroup is the
only one where processes and subgroups are still allowed, but in order
to support containers nicey, we move PID 1 into the new scope in all
cases.) This new unit is also used on legacy hierarchy setups. It's
actually pretty useful on all systems, as it can then be used to filter
journal messages coming from PID 1, and so on.
The root slice ("-.slice") is now implicitly created and started (and
does not require a unit file on disk anymore), since
that's where "init.scope" is located and the slice needs to be started
before the scope can.
To check whether we are in unified or legacy hierarchy mode we use
statfs() on /sys/fs/cgroup. If the .f_type field reports tmpfs we are in
legacy mode, if it reports cgroupfs we are in unified mode.
This patch set carefuly makes sure that cgls and cgtop continue to work
as desired.
When invoking nspawn as a service it will implicitly create two
subcgroups in the cgroup it is using, one to move the nspawn process
into, the other to move the actual container processes into. This is
done because of the requirement that cgroups may either contain
processes or other subgroups.
2015-09-01 19:22:36 +02:00
|
|
|
if (!u) {
|
2018-02-04 21:46:27 +01:00
|
|
|
r = unit_new_for_name(m, sizeof(Slice), name, &u);
|
2018-02-09 19:07:01 +01:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to allocate the special %s unit: %m", name);
|
core: unified cgroup hierarchy support
This patch set adds full support the new unified cgroup hierarchy logic
of modern kernels.
A new kernel command line option "systemd.unified_cgroup_hierarchy=1" is
added. If specified the unified hierarchy is mounted to /sys/fs/cgroup
instead of a tmpfs. No further hierarchies are mounted. The kernel
command line option defaults to off. We can turn it on by default as
soon as the kernel's APIs regarding this are stabilized (but even then
downstream distros might want to turn this off, as this will break any
tools that access cgroupfs directly).
It is possibly to choose for each boot individually whether the unified
or the legacy hierarchy is used. nspawn will by default provide the
legacy hierarchy to containers if the host is using it, and the unified
otherwise. However it is possible to run containers with the unified
hierarchy on a legacy host and vice versa, by setting the
$UNIFIED_CGROUP_HIERARCHY environment variable for nspawn to 1 or 0,
respectively.
The unified hierarchy provides reliable cgroup empty notifications for
the first time, via inotify. To make use of this we maintain one
manager-wide inotify fd, and each cgroup to it.
This patch also removes cg_delete() which is unused now.
On kernel 4.2 only the "memory" controller is compatible with the
unified hierarchy, hence that's the only controller systemd exposes when
booted in unified heirarchy mode.
This introduces a new enum for enumerating supported controllers, plus a
related enum for the mask bits mapping to it. The core is changed to
make use of this everywhere.
This moves PID 1 into a new "init.scope" implicit scope unit in the root
slice. This is necessary since on the unified hierarchy cgroups may
either contain subgroups or processes but not both. PID 1 hence has to
move out of the root cgroup (strictly speaking the root cgroup is the
only one where processes and subgroups are still allowed, but in order
to support containers nicey, we move PID 1 into the new scope in all
cases.) This new unit is also used on legacy hierarchy setups. It's
actually pretty useful on all systems, as it can then be used to filter
journal messages coming from PID 1, and so on.
The root slice ("-.slice") is now implicitly created and started (and
does not require a unit file on disk anymore), since
that's where "init.scope" is located and the slice needs to be started
before the scope can.
To check whether we are in unified or legacy hierarchy mode we use
statfs() on /sys/fs/cgroup. If the .f_type field reports tmpfs we are in
legacy mode, if it reports cgroupfs we are in unified mode.
This patch set carefuly makes sure that cgls and cgtop continue to work
as desired.
When invoking nspawn as a service it will implicitly create two
subcgroups in the cgroup it is using, one to move the nspawn process
into, the other to move the actual container processes into. This is
done because of the requirement that cgroups may either contain
processes or other subgroups.
2015-09-01 19:22:36 +02:00
|
|
|
}
|
|
|
|
|
2016-10-24 21:41:54 +02:00
|
|
|
u->perpetual = true;
|
core: unified cgroup hierarchy support
This patch set adds full support the new unified cgroup hierarchy logic
of modern kernels.
A new kernel command line option "systemd.unified_cgroup_hierarchy=1" is
added. If specified the unified hierarchy is mounted to /sys/fs/cgroup
instead of a tmpfs. No further hierarchies are mounted. The kernel
command line option defaults to off. We can turn it on by default as
soon as the kernel's APIs regarding this are stabilized (but even then
downstream distros might want to turn this off, as this will break any
tools that access cgroupfs directly).
It is possibly to choose for each boot individually whether the unified
or the legacy hierarchy is used. nspawn will by default provide the
legacy hierarchy to containers if the host is using it, and the unified
otherwise. However it is possible to run containers with the unified
hierarchy on a legacy host and vice versa, by setting the
$UNIFIED_CGROUP_HIERARCHY environment variable for nspawn to 1 or 0,
respectively.
The unified hierarchy provides reliable cgroup empty notifications for
the first time, via inotify. To make use of this we maintain one
manager-wide inotify fd, and each cgroup to it.
This patch also removes cg_delete() which is unused now.
On kernel 4.2 only the "memory" controller is compatible with the
unified hierarchy, hence that's the only controller systemd exposes when
booted in unified heirarchy mode.
This introduces a new enum for enumerating supported controllers, plus a
related enum for the mask bits mapping to it. The core is changed to
make use of this everywhere.
This moves PID 1 into a new "init.scope" implicit scope unit in the root
slice. This is necessary since on the unified hierarchy cgroups may
either contain subgroups or processes but not both. PID 1 hence has to
move out of the root cgroup (strictly speaking the root cgroup is the
only one where processes and subgroups are still allowed, but in order
to support containers nicey, we move PID 1 into the new scope in all
cases.) This new unit is also used on legacy hierarchy setups. It's
actually pretty useful on all systems, as it can then be used to filter
journal messages coming from PID 1, and so on.
The root slice ("-.slice") is now implicitly created and started (and
does not require a unit file on disk anymore), since
that's where "init.scope" is located and the slice needs to be started
before the scope can.
To check whether we are in unified or legacy hierarchy mode we use
statfs() on /sys/fs/cgroup. If the .f_type field reports tmpfs we are in
legacy mode, if it reports cgroupfs we are in unified mode.
This patch set carefuly makes sure that cgls and cgtop continue to work
as desired.
When invoking nspawn as a service it will implicitly create two
subcgroups in the cgroup it is using, one to move the nspawn process
into, the other to move the actual container processes into. This is
done because of the requirement that cgroups may either contain
processes or other subgroups.
2015-09-01 19:22:36 +02:00
|
|
|
SLICE(u)->deserialized_state = SLICE_ACTIVE;
|
|
|
|
|
|
|
|
unit_add_to_load_queue(u);
|
|
|
|
unit_add_to_dbus_queue(u);
|
2018-02-09 19:07:01 +01:00
|
|
|
|
|
|
|
if (ret)
|
|
|
|
*ret = u;
|
|
|
|
|
|
|
|
return 0;
|
core: unified cgroup hierarchy support
This patch set adds full support the new unified cgroup hierarchy logic
of modern kernels.
A new kernel command line option "systemd.unified_cgroup_hierarchy=1" is
added. If specified the unified hierarchy is mounted to /sys/fs/cgroup
instead of a tmpfs. No further hierarchies are mounted. The kernel
command line option defaults to off. We can turn it on by default as
soon as the kernel's APIs regarding this are stabilized (but even then
downstream distros might want to turn this off, as this will break any
tools that access cgroupfs directly).
It is possibly to choose for each boot individually whether the unified
or the legacy hierarchy is used. nspawn will by default provide the
legacy hierarchy to containers if the host is using it, and the unified
otherwise. However it is possible to run containers with the unified
hierarchy on a legacy host and vice versa, by setting the
$UNIFIED_CGROUP_HIERARCHY environment variable for nspawn to 1 or 0,
respectively.
The unified hierarchy provides reliable cgroup empty notifications for
the first time, via inotify. To make use of this we maintain one
manager-wide inotify fd, and each cgroup to it.
This patch also removes cg_delete() which is unused now.
On kernel 4.2 only the "memory" controller is compatible with the
unified hierarchy, hence that's the only controller systemd exposes when
booted in unified heirarchy mode.
This introduces a new enum for enumerating supported controllers, plus a
related enum for the mask bits mapping to it. The core is changed to
make use of this everywhere.
This moves PID 1 into a new "init.scope" implicit scope unit in the root
slice. This is necessary since on the unified hierarchy cgroups may
either contain subgroups or processes but not both. PID 1 hence has to
move out of the root cgroup (strictly speaking the root cgroup is the
only one where processes and subgroups are still allowed, but in order
to support containers nicey, we move PID 1 into the new scope in all
cases.) This new unit is also used on legacy hierarchy setups. It's
actually pretty useful on all systems, as it can then be used to filter
journal messages coming from PID 1, and so on.
The root slice ("-.slice") is now implicitly created and started (and
does not require a unit file on disk anymore), since
that's where "init.scope" is located and the slice needs to be started
before the scope can.
To check whether we are in unified or legacy hierarchy mode we use
statfs() on /sys/fs/cgroup. If the .f_type field reports tmpfs we are in
legacy mode, if it reports cgroupfs we are in unified mode.
This patch set carefuly makes sure that cgls and cgtop continue to work
as desired.
When invoking nspawn as a service it will implicitly create two
subcgroups in the cgroup it is using, one to move the nspawn process
into, the other to move the actual container processes into. This is
done because of the requirement that cgroups may either contain
processes or other subgroups.
2015-09-01 19:22:36 +02:00
|
|
|
}
|
|
|
|
|
core: enumerate perpetual units in a separate per-unit-type method
Previously the enumerate() callback defined for each unit type would do
two things:
1. It would create perpetual units (i.e. -.slice, system.slice, -.mount and
init.scope)
2. It would enumerate units from /proc/self/mountinfo, /proc/swaps and
the udev database
With this change these two parts are split into two seperate methods:
enumerate() now only does #2, while enumerate_perpetual() is responsible
for #1. Why make this change? Well, perpetual units should have a
slightly different effect that those found through enumeration: as
perpetual units should be up unconditionally, perpetually and thus never
change state, they should also not pull in deps by their state changing,
not even when the state is first set to active. Thus, their state is
generally initialized through the per-device coldplug() method in
similar fashion to the deserialized state from a previous run would be
put into place. OTOH units found through regular enumeration should
result in state changes (and thus pull in deps due to state changes),
hence their state should be put in effect in the catchup() method
instead. Hence, given this difference, let's also separate the
functions, so that the rule is:
1. What is created in enumerate_perpetual() should be started in
coldplug()
2. What is created in enumerate() should be started in catchup().
2018-06-05 18:26:45 +02:00
|
|
|
static void slice_enumerate_perpetual(Manager *m) {
|
2018-02-09 19:07:01 +01:00
|
|
|
Unit *u;
|
|
|
|
int r;
|
|
|
|
|
2018-02-04 21:46:27 +01:00
|
|
|
assert(m);
|
|
|
|
|
2018-02-09 19:07:01 +01:00
|
|
|
r = slice_make_perpetual(m, SPECIAL_ROOT_SLICE, &u);
|
2018-11-20 22:42:16 +01:00
|
|
|
if (r >= 0 && manager_owns_host_root_cgroup(m)) {
|
2018-02-09 19:07:01 +01:00
|
|
|
Slice *s = SLICE(u);
|
|
|
|
|
|
|
|
/* If we are managing the root cgroup then this means our root slice covers the whole system, which
|
|
|
|
* means the kernel will track CPU/tasks/memory for us anyway, and it is all available in /proc. Let's
|
|
|
|
* hence turn accounting on here, so that our APIs to query this data are available. */
|
|
|
|
|
|
|
|
s->cgroup_context.cpu_accounting = true;
|
|
|
|
s->cgroup_context.tasks_accounting = true;
|
|
|
|
s->cgroup_context.memory_accounting = true;
|
|
|
|
}
|
2018-02-04 21:46:27 +01:00
|
|
|
|
|
|
|
if (MANAGER_IS_SYSTEM(m))
|
2018-02-09 19:07:01 +01:00
|
|
|
(void) slice_make_perpetual(m, SPECIAL_SYSTEM_SLICE, NULL);
|
2018-02-04 21:46:27 +01:00
|
|
|
}
|
|
|
|
|
2020-04-29 17:53:43 +02:00
|
|
|
static bool slice_freezer_action_supported_by_children(Unit *s) {
|
|
|
|
Unit *member;
|
|
|
|
void *v;
|
|
|
|
|
|
|
|
assert(s);
|
|
|
|
|
2020-09-08 11:58:29 +02:00
|
|
|
HASHMAP_FOREACH_KEY(v, member, s->dependencies[UNIT_BEFORE]) {
|
2020-04-29 17:53:43 +02:00
|
|
|
int r;
|
|
|
|
|
|
|
|
if (UNIT_DEREF(member->slice) != s)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (member->type == UNIT_SLICE) {
|
|
|
|
r = slice_freezer_action_supported_by_children(member);
|
|
|
|
if (!r)
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!UNIT_VTABLE(member)->freeze)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int slice_freezer_action(Unit *s, FreezerAction action) {
|
|
|
|
Unit *member;
|
|
|
|
void *v;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(s);
|
|
|
|
assert(IN_SET(action, FREEZER_FREEZE, FREEZER_THAW));
|
|
|
|
|
2020-09-08 19:27:56 +02:00
|
|
|
if (!slice_freezer_action_supported_by_children(s)) {
|
|
|
|
log_unit_warning(s, "Requested freezer operation is not supported by all children of the slice");
|
|
|
|
return 0;
|
|
|
|
}
|
2020-04-29 17:53:43 +02:00
|
|
|
|
2020-09-08 11:58:29 +02:00
|
|
|
HASHMAP_FOREACH_KEY(v, member, s->dependencies[UNIT_BEFORE]) {
|
2020-04-29 17:53:43 +02:00
|
|
|
if (UNIT_DEREF(member->slice) != s)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (action == FREEZER_FREEZE)
|
|
|
|
r = UNIT_VTABLE(member)->freeze(member);
|
|
|
|
else
|
|
|
|
r = UNIT_VTABLE(member)->thaw(member);
|
|
|
|
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = unit_cgroup_freezer_action(s, action);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2020-06-05 15:23:12 +02:00
|
|
|
return 1;
|
2020-04-29 17:53:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static int slice_freeze(Unit *s) {
|
|
|
|
assert(s);
|
|
|
|
|
|
|
|
return slice_freezer_action(s, FREEZER_FREEZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int slice_thaw(Unit *s) {
|
|
|
|
assert(s);
|
|
|
|
|
|
|
|
return slice_freezer_action(s, FREEZER_THAW);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool slice_can_freeze(Unit *s) {
|
|
|
|
assert(s);
|
|
|
|
|
|
|
|
return slice_freezer_action_supported_by_children(s);
|
|
|
|
}
|
|
|
|
|
2013-06-17 21:33:26 +02:00
|
|
|
const UnitVTable slice_vtable = {
|
|
|
|
.object_size = sizeof(Slice),
|
2013-11-19 21:12:59 +01:00
|
|
|
.cgroup_context_offset = offsetof(Slice, cgroup_context),
|
|
|
|
|
2013-06-17 21:33:26 +02:00
|
|
|
.sections =
|
|
|
|
"Unit\0"
|
|
|
|
"Slice\0"
|
|
|
|
"Install\0",
|
2013-06-27 04:14:27 +02:00
|
|
|
.private_section = "Slice",
|
|
|
|
|
2015-11-13 18:46:50 +01:00
|
|
|
.can_transient = true,
|
2020-03-09 23:09:17 +01:00
|
|
|
.can_set_managed_oom = true,
|
2013-06-17 21:33:26 +02:00
|
|
|
|
2016-02-18 22:51:23 +01:00
|
|
|
.init = slice_init,
|
2013-06-17 21:33:26 +02:00
|
|
|
.load = slice_load,
|
2013-06-27 04:14:27 +02:00
|
|
|
|
2013-06-17 21:33:26 +02:00
|
|
|
.coldplug = slice_coldplug,
|
|
|
|
|
|
|
|
.dump = slice_dump,
|
|
|
|
|
|
|
|
.start = slice_start,
|
|
|
|
.stop = slice_stop,
|
|
|
|
|
|
|
|
.kill = slice_kill,
|
|
|
|
|
2020-04-29 17:53:43 +02:00
|
|
|
.freeze = slice_freeze,
|
|
|
|
.thaw = slice_thaw,
|
|
|
|
.can_freeze = slice_can_freeze,
|
|
|
|
|
2013-06-17 21:33:26 +02:00
|
|
|
.serialize = slice_serialize,
|
|
|
|
.deserialize_item = slice_deserialize_item,
|
|
|
|
|
|
|
|
.active_state = slice_active_state,
|
|
|
|
.sub_state_to_string = slice_sub_state_to_string,
|
|
|
|
|
2013-06-27 21:14:56 +02:00
|
|
|
.bus_set_property = bus_slice_set_property,
|
|
|
|
.bus_commit_properties = bus_slice_commit_properties,
|
2013-06-17 21:33:26 +02:00
|
|
|
|
core: enumerate perpetual units in a separate per-unit-type method
Previously the enumerate() callback defined for each unit type would do
two things:
1. It would create perpetual units (i.e. -.slice, system.slice, -.mount and
init.scope)
2. It would enumerate units from /proc/self/mountinfo, /proc/swaps and
the udev database
With this change these two parts are split into two seperate methods:
enumerate() now only does #2, while enumerate_perpetual() is responsible
for #1. Why make this change? Well, perpetual units should have a
slightly different effect that those found through enumeration: as
perpetual units should be up unconditionally, perpetually and thus never
change state, they should also not pull in deps by their state changing,
not even when the state is first set to active. Thus, their state is
generally initialized through the per-device coldplug() method in
similar fashion to the deserialized state from a previous run would be
put into place. OTOH units found through regular enumeration should
result in state changes (and thus pull in deps due to state changes),
hence their state should be put in effect in the catchup() method
instead. Hence, given this difference, let's also separate the
functions, so that the rule is:
1. What is created in enumerate_perpetual() should be started in
coldplug()
2. What is created in enumerate() should be started in catchup().
2018-06-05 18:26:45 +02:00
|
|
|
.enumerate_perpetual = slice_enumerate_perpetual,
|
core: unified cgroup hierarchy support
This patch set adds full support the new unified cgroup hierarchy logic
of modern kernels.
A new kernel command line option "systemd.unified_cgroup_hierarchy=1" is
added. If specified the unified hierarchy is mounted to /sys/fs/cgroup
instead of a tmpfs. No further hierarchies are mounted. The kernel
command line option defaults to off. We can turn it on by default as
soon as the kernel's APIs regarding this are stabilized (but even then
downstream distros might want to turn this off, as this will break any
tools that access cgroupfs directly).
It is possibly to choose for each boot individually whether the unified
or the legacy hierarchy is used. nspawn will by default provide the
legacy hierarchy to containers if the host is using it, and the unified
otherwise. However it is possible to run containers with the unified
hierarchy on a legacy host and vice versa, by setting the
$UNIFIED_CGROUP_HIERARCHY environment variable for nspawn to 1 or 0,
respectively.
The unified hierarchy provides reliable cgroup empty notifications for
the first time, via inotify. To make use of this we maintain one
manager-wide inotify fd, and each cgroup to it.
This patch also removes cg_delete() which is unused now.
On kernel 4.2 only the "memory" controller is compatible with the
unified hierarchy, hence that's the only controller systemd exposes when
booted in unified heirarchy mode.
This introduces a new enum for enumerating supported controllers, plus a
related enum for the mask bits mapping to it. The core is changed to
make use of this everywhere.
This moves PID 1 into a new "init.scope" implicit scope unit in the root
slice. This is necessary since on the unified hierarchy cgroups may
either contain subgroups or processes but not both. PID 1 hence has to
move out of the root cgroup (strictly speaking the root cgroup is the
only one where processes and subgroups are still allowed, but in order
to support containers nicey, we move PID 1 into the new scope in all
cases.) This new unit is also used on legacy hierarchy setups. It's
actually pretty useful on all systems, as it can then be used to filter
journal messages coming from PID 1, and so on.
The root slice ("-.slice") is now implicitly created and started (and
does not require a unit file on disk anymore), since
that's where "init.scope" is located and the slice needs to be started
before the scope can.
To check whether we are in unified or legacy hierarchy mode we use
statfs() on /sys/fs/cgroup. If the .f_type field reports tmpfs we are in
legacy mode, if it reports cgroupfs we are in unified mode.
This patch set carefuly makes sure that cgls and cgtop continue to work
as desired.
When invoking nspawn as a service it will implicitly create two
subcgroups in the cgroup it is using, one to move the nspawn process
into, the other to move the actual container processes into. This is
done because of the requirement that cgroups may either contain
processes or other subgroups.
2015-09-01 19:22:36 +02:00
|
|
|
|
2013-06-17 21:33:26 +02:00
|
|
|
.status_message_formats = {
|
|
|
|
.finished_start_job = {
|
2013-06-27 04:14:27 +02:00
|
|
|
[JOB_DONE] = "Created slice %s.",
|
2013-06-17 21:33:26 +02:00
|
|
|
},
|
|
|
|
.finished_stop_job = {
|
2013-06-27 04:14:27 +02:00
|
|
|
[JOB_DONE] = "Removed slice %s.",
|
2013-06-17 21:33:26 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
};
|