diff options
author | Tejun Heo <htejun@fb.com> | 2016-08-15 18:13:36 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2016-08-17 17:44:36 -0400 |
commit | 5da38d0768bf53f611ccdd47d7d941e1c560e44e (patch) | |
tree | 73ab0b904fca6a1e08e4904467efb82be01d4d06 /src/nspawn/nspawn-mount.c | |
parent | ca2f6384aa2076576b316c7253964be90b102d96 (diff) |
core: use the unified hierarchy for the systemd cgroup controller hierarchy
Currently, systemd uses either the legacy hierarchies or the unified hierarchy.
When the legacy hierarchies are used, systemd uses a named legacy hierarchy
mounted on /sys/fs/cgroup/systemd without any kernel controllers for process
management. Due to the shortcomings in the legacy hierarchy, this involves a
lot of workarounds and complexities.
Because the unified hierarchy can be mounted and used in parallel to legacy
hierarchies, there's no reason for systemd to use a legacy hierarchy for
management even if the kernel resource controllers need to be mounted on legacy
hierarchies. It can simply mount the unified hierarchy under
/sys/fs/cgroup/systemd and use it without affecting other legacy hierarchies.
This disables a significant amount of fragile workaround logics and would allow
using features which depend on the unified hierarchy membership such bpf cgroup
v2 membership test. In time, this would also allow deleting the said
complexities.
This patch updates systemd so that it prefers the unified hierarchy for the
systemd cgroup controller hierarchy when legacy hierarchies are used for kernel
resource controllers.
* cg_unified(@controller) is introduced which tests whether the specific
controller in on unified hierarchy and used to choose the unified hierarchy
code path for process and service management when available. Kernel
controller specific operations remain gated by cg_all_unified().
* "systemd.legacy_systemd_cgroup_controller" kernel argument can be used to
force the use of legacy hierarchy for systemd cgroup controller.
* nspawn: By default nspawn uses the same hierarchies as the host. If
UNIFIED_CGROUP_HIERARCHY is set to 1, unified hierarchy is used for all. If
0, legacy for all.
* nspawn: arg_unified_cgroup_hierarchy is made an enum and now encodes one of
three options - legacy, only systemd controller on unified, and unified. The
value is passed into mount setup functions and controls cgroup configuration.
* nspawn: Interpretation of SYSTEMD_CGROUP_CONTROLLER to the actual mount
option is moved to mount_legacy_cgroup_hierarchy() so that it can take an
appropriate action depending on the configuration of the host.
v2: - CGroupUnified enum replaces open coded integer values to indicate the
cgroup operation mode.
- Various style updates.
v3: Fixed a bug in detect_unified_cgroup_hierarchy() introduced during v2.
v4: Restored legacy container on unified host support and fixed another bug in
detect_unified_cgroup_hierarchy().
Diffstat (limited to 'src/nspawn/nspawn-mount.c')
-rw-r--r-- | src/nspawn/nspawn-mount.c | 42 |
1 files changed, 25 insertions, 17 deletions
diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index b5d83d481a..295b75341f 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -21,7 +21,6 @@ #include <linux/magic.h> #include "alloc-util.h" -#include "cgroup-util.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" @@ -661,7 +660,8 @@ static int get_controllers(Set *subsystems) { return 0; } -static int mount_legacy_cgroup_hierarchy(const char *dest, const char *controller, const char *hierarchy, bool read_only) { +static int mount_legacy_cgroup_hierarchy(const char *dest, const char *controller, const char *hierarchy, + CGroupUnified unified_requested, bool read_only) { char *to; int r; @@ -677,7 +677,15 @@ static int mount_legacy_cgroup_hierarchy(const char *dest, const char *controlle /* The superblock mount options of the mount point need to be * identical to the hosts', and hence writable... */ - if (mount("cgroup", to, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, controller) < 0) + if (streq(controller, SYSTEMD_CGROUP_CONTROLLER)) { + if (unified_requested >= CGROUP_UNIFIED_SYSTEMD) + r = mount("cgroup", to, "cgroup2", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); + else + r = mount("cgroup", to, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, "none,name=systemd,xattr"); + } else + r = mount("cgroup", to, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, controller); + + if (r < 0) return log_error_errno(errno, "Failed to mount to %s: %m", to); /* ... hence let's only make the bind mount read-only, not the @@ -691,8 +699,8 @@ static int mount_legacy_cgroup_hierarchy(const char *dest, const char *controlle /* Mount a legacy cgroup hierarchy when cgroup namespaces are supported. */ static int mount_legacy_cgns_supported( - bool userns, uid_t uid_shift, uid_t uid_range, - const char *selinux_apifs_context) { + CGroupUnified unified_requested, bool userns, uid_t uid_shift, + uid_t uid_range, const char *selinux_apifs_context) { _cleanup_set_free_free_ Set *controllers = NULL; const char *cgroup_root = "/sys/fs/cgroup", *c; int r; @@ -739,7 +747,7 @@ static int mount_legacy_cgns_supported( if (!controller) break; - r = mount_legacy_cgroup_hierarchy("", controller, controller, !userns); + r = mount_legacy_cgroup_hierarchy("", controller, controller, unified_requested, !userns); if (r < 0) return r; @@ -773,7 +781,7 @@ static int mount_legacy_cgns_supported( } skip_controllers: - r = mount_legacy_cgroup_hierarchy("", "none,name=systemd,xattr", "systemd", false); + r = mount_legacy_cgroup_hierarchy("", SYSTEMD_CGROUP_CONTROLLER, "systemd", unified_requested, false); if (r < 0) return r; @@ -788,7 +796,7 @@ skip_controllers: /* Mount legacy cgroup hierarchy when cgroup namespaces are unsupported. */ static int mount_legacy_cgns_unsupported( const char *dest, - bool userns, uid_t uid_shift, uid_t uid_range, + CGroupUnified unified_requested, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context) { _cleanup_set_free_free_ Set *controllers = NULL; const char *cgroup_root; @@ -839,7 +847,7 @@ static int mount_legacy_cgns_unsupported( if (r == -EINVAL) { /* Not a symbolic link, but directly a single cgroup hierarchy */ - r = mount_legacy_cgroup_hierarchy(dest, controller, controller, true); + r = mount_legacy_cgroup_hierarchy(dest, controller, controller, unified_requested, true); if (r < 0) return r; @@ -859,7 +867,7 @@ static int mount_legacy_cgns_unsupported( continue; } - r = mount_legacy_cgroup_hierarchy(dest, combined, combined, true); + r = mount_legacy_cgroup_hierarchy(dest, combined, combined, unified_requested, true); if (r < 0) return r; @@ -872,7 +880,7 @@ static int mount_legacy_cgns_unsupported( } skip_controllers: - r = mount_legacy_cgroup_hierarchy(dest, "none,name=systemd,xattr", "systemd", false); + r = mount_legacy_cgroup_hierarchy(dest, SYSTEMD_CGROUP_CONTROLLER, "systemd", unified_requested, false); if (r < 0) return r; @@ -914,22 +922,22 @@ static int mount_unified_cgroups(const char *dest) { int mount_cgroups( const char *dest, - bool unified_requested, + CGroupUnified unified_requested, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context, bool use_cgns) { - if (unified_requested) + if (unified_requested >= CGROUP_UNIFIED_ALL) return mount_unified_cgroups(dest); else if (use_cgns && cg_ns_supported()) - return mount_legacy_cgns_supported(userns, uid_shift, uid_range, selinux_apifs_context); + return mount_legacy_cgns_supported(unified_requested, userns, uid_shift, uid_range, selinux_apifs_context); - return mount_legacy_cgns_unsupported(dest, userns, uid_shift, uid_range, selinux_apifs_context); + return mount_legacy_cgns_unsupported(dest, unified_requested, userns, uid_shift, uid_range, selinux_apifs_context); } int mount_systemd_cgroup_writable( const char *dest, - bool unified_requested) { + CGroupUnified unified_requested) { _cleanup_free_ char *own_cgroup_path = NULL; const char *systemd_root, *systemd_own; @@ -945,7 +953,7 @@ int mount_systemd_cgroup_writable( if (path_equal(own_cgroup_path, "/")) return 0; - if (unified_requested) { + if (unified_requested >= CGROUP_UNIFIED_ALL) { systemd_own = strjoina(dest, "/sys/fs/cgroup", own_cgroup_path); systemd_root = prefix_roota(dest, "/sys/fs/cgroup"); } else { |