summaryrefslogtreecommitdiff
path: root/src/core/cgroup.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@fb.com>2016-08-15 18:13:36 -0400
committerSven Eden <yamakuzure@gmx.net>2017-07-05 08:50:51 +0200
commitd4ce8390c5aa345602b51099e9d3ed3b74d3ec4d (patch)
tree5db9e4133d5eb5993625a6dc07dfa3d33e1322ba /src/core/cgroup.c
parent87a9605f2154237a49d3da054cad782dfcc1d2d2 (diff)
core: use the unified hierarchy for the elogind cgroup controller hierarchy
Currently, elogind uses either the legacy hierarchies or the unified hierarchy. When the legacy hierarchies are used, elogind uses a named legacy hierarchy mounted on /sys/fs/cgroup/elogind 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 elogind 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/elogind 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 elogind so that it prefers the unified hierarchy for the elogind 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(). * "elogind.legacy_elogind_cgroup_controller" kernel argument can be used to force the use of legacy hierarchy for elogind 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 elogind 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/core/cgroup.c')
-rw-r--r--src/core/cgroup.c34
1 files changed, 20 insertions, 14 deletions
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index b53b35dad..56f065fdb 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -666,7 +666,7 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) {
bool has_weight = cgroup_context_has_cpu_weight(c);
bool has_shares = cgroup_context_has_cpu_shares(c);
- if (cg_unified() > 0) {
+ if (cg_all_unified() > 0) {
uint64_t weight;
if (has_weight)
@@ -847,7 +847,7 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) {
}
if ((mask & CGROUP_MASK_MEMORY) && !is_root) {
- if (cg_unified() > 0) {
+ if (cg_all_unified() > 0) {
uint64_t max = c->memory_max;
if (cgroup_context_has_unified_memory_config(c))
@@ -1021,7 +1021,7 @@ CGroupMask unit_get_own_mask(Unit *u) {
e = unit_get_exec_context(u);
if (!e ||
exec_context_maintains_privileges(e) ||
- cg_unified() > 0)
+ cg_all_unified() > 0)
return _CGROUP_MASK_ALL;
}
@@ -1247,7 +1247,7 @@ int unit_watch_cgroup(Unit *u) {
return 0;
/* Only applies to the unified hierarchy */
- r = cg_unified();
+ r = cg_unified(SYSTEMD_CGROUP_CONTROLLER);
if (r < 0)
return log_unit_error_errno(u, r, "Failed detect whether the unified hierarchy is used: %m");
if (r == 0)
@@ -1647,7 +1647,7 @@ int unit_watch_all_pids(Unit *u) {
if (!u->cgroup_path)
return -ENOENT;
- if (cg_unified() > 0) /* On unified we can use proper notifications */
+ if (cg_unified(SYSTEMD_CGROUP_CONTROLLER) > 0) /* On unified we can use proper notifications */
return 0;
return unit_watch_pids_in_path(u, u->cgroup_path);
@@ -1721,7 +1721,7 @@ static int on_cgroup_inotify_event(sd_event_source *s, int fd, uint32_t revents,
int manager_setup_cgroup(Manager *m) {
_cleanup_free_ char *path = NULL;
CGroupController c;
- int r, unified;
+ int r, all_unified, systemd_unified;
char *e;
assert(m);
@@ -1762,11 +1762,17 @@ int manager_setup_cgroup(Manager *m) {
if (r < 0)
return log_error_errno(r, "Cannot find cgroup mount point: %m");
- unified = cg_unified();
- if (unified < 0)
- return log_error_errno(r, "Couldn't determine if we are running in the unified hierarchy: %m");
- if (unified > 0)
+ all_unified = cg_all_unified();
+ systemd_unified = cg_unified(SYSTEMD_CGROUP_CONTROLLER);
+
+ if (all_unified < 0 || systemd_unified < 0)
+ return log_error_errno(all_unified < 0 ? all_unified : systemd_unified,
+ "Couldn't determine if we are running in the unified hierarchy: %m");
+
+ if (all_unified > 0)
log_debug("Unified cgroup hierarchy is located at %s.", path);
+ else if (systemd_unified > 0)
+ log_debug("Unified cgroup hierarchy is located at %s. Controllers are on legacy hierarchies.", path);
else
log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER ". File system hierarchy is at %s.", path);
@@ -1774,7 +1780,7 @@ int manager_setup_cgroup(Manager *m) {
const char *scope_path;
/* 3. Install agent */
- if (unified) {
+ if (systemd_unified) {
/* In the unified hierarchy we can get
* cgroup empty notifications via inotify. */
@@ -1852,7 +1858,7 @@ int manager_setup_cgroup(Manager *m) {
return log_error_errno(errno, "Failed to open pin file: %m");
/* 6. Always enable hierarchical support if it exists... */
- if (!unified)
+ if (!all_unified)
(void) cg_set_attribute("memory", "/", "memory.use_hierarchy", "1");
}
@@ -2004,7 +2010,7 @@ int unit_get_memory_current(Unit *u, uint64_t *ret) {
if ((u->cgroup_realized_mask & CGROUP_MASK_MEMORY) == 0)
return -ENODATA;
- if (cg_unified() <= 0)
+ if (cg_all_unified() <= 0)
r = cg_get_attribute("memory", u->cgroup_path, "memory.usage_in_bytes", &v);
else
r = cg_get_attribute("memory", u->cgroup_path, "memory.current", &v);
@@ -2049,7 +2055,7 @@ static int unit_get_cpu_usage_raw(Unit *u, nsec_t *ret) {
if (!u->cgroup_path)
return -ENODATA;
- if (cg_unified() > 0) {
+ if (cg_all_unified() > 0) {
const char *keys[] = { "usage_usec", NULL };
_cleanup_free_ char *val = NULL;
uint64_t us;