X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcore%2Fcgroup.c;h=04816239cc39ddfad6ca2590919be34e94b3ef5c;hp=a524a411004615d6ba67c3ea51419331a5a3c22f;hb=HEAD;hpb=910c586574a52c6b4cbc6638193797008da076c7 diff --git a/src/core/cgroup.c b/src/core/cgroup.c index a524a4110..04816239c 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -288,14 +288,24 @@ static int lookup_block_device(const char *p, dev_t *dev) { static int whitelist_device(const char *path, const char *node, const char *acc) { char buf[2+DECIMAL_STR_MAX(dev_t)*2+2+4]; struct stat st; + bool ignore_notfound; int r; assert(path); assert(acc); + if (node[0] == '-') { + /* Non-existent paths starting with "-" must be silently ignored */ + node++; + ignore_notfound = true; + } else + ignore_notfound = false; + if (stat(node, &st) < 0) { - log_warning("Couldn't stat device %s", node); - return -errno; + if (errno == ENOENT && ignore_notfound) + return 0; + + return log_warning_errno(errno, "Couldn't stat device %s: %m", node); } if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) { @@ -389,8 +399,7 @@ static int whitelist_major(const char *path, const char *name, char type, const return 0; fail: - log_warning_errno(errno, "Failed to read /proc/devices: %m"); - return -errno; + return log_warning_errno(errno, "Failed to read /proc/devices: %m"); } static bool cgroup_context_has_cpu_weight(CGroupContext *c) { @@ -850,8 +859,7 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) { if ((mask & CGROUP_MASK_MEMORY) && !is_root) { if (cg_all_unified() > 0) { - uint64_t max; - uint64_t swap_max = CGROUP_LIMIT_MAX; + uint64_t max, swap_max = CGROUP_LIMIT_MAX; if (cgroup_context_has_unified_memory_config(c)) { max = c->memory_max; @@ -916,8 +924,8 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) { "/dev/pts/ptmx\0" "rw\0" /* /dev/pts/ptmx may not be duplicated, but accessed */ /* Allow /run/elogind/inaccessible/{chr,blk} devices for mapping InaccessiblePaths */ /* Allow /run/systemd/inaccessible/{chr,blk} devices for mapping InaccessiblePaths */ - "/run/systemd/inaccessible/chr\0" "rwm\0" - "/run/systemd/inaccessible/blk\0" "rwm\0"; + "-/run/systemd/inaccessible/chr\0" "rwm\0" + "-/run/systemd/inaccessible/blk\0" "rwm\0"; const char *x, *y; @@ -1203,9 +1211,10 @@ char *unit_default_cgroup_path(Unit *u) { return NULL; if (slice) - return strjoin(u->manager->cgroup_root, "/", slice, "/", escaped, NULL); + return strjoin(u->manager->cgroup_root, "/", slice, "/", + escaped); else - return strjoin(u->manager->cgroup_root, "/", escaped, NULL); + return strjoin(u->manager->cgroup_root, "/", escaped); } int unit_set_cgroup_path(Unit *u, const char *path) { @@ -1251,9 +1260,9 @@ int unit_watch_cgroup(Unit *u) { return 0; /* Only applies to the unified hierarchy */ - r = cg_unified(SYSTEMD_CGROUP_CONTROLLER); + r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); if (r < 0) - return log_unit_error_errno(u, r, "Failed detect whether the unified hierarchy is used: %m"); + return log_error_errno(r, "Failed to determine whether the name=systemd hierarchy is unified: %m"); if (r == 0) return 0; @@ -1645,7 +1654,7 @@ static int unit_watch_pids_in_path(Unit *u, const char *path) { while ((r = cg_read_subgroup(d, &fn)) > 0) { _cleanup_free_ char *p = NULL; - p = strjoin(path, "/", fn, NULL); + p = strjoin(path, "/", fn); free(fn); if (!p) @@ -1664,6 +1673,8 @@ static int unit_watch_pids_in_path(Unit *u, const char *path) { } int unit_watch_all_pids(Unit *u) { + int r; + assert(u); /* Adds all PIDs from our cgroup to the set of PIDs we @@ -1674,7 +1685,10 @@ int unit_watch_all_pids(Unit *u) { if (!u->cgroup_path) return -ENOENT; - if (cg_unified(SYSTEMD_CGROUP_CONTROLLER) > 0) /* On unified we can use proper notifications */ + r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); + if (r < 0) + return r; + if (r > 0) /* On unified we can use proper notifications */ return 0; return unit_watch_pids_in_path(u, u->cgroup_path); @@ -1748,14 +1762,18 @@ 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, all_unified, systemd_unified; + int r, all_unified; char *e; assert(m); /* 1. Determine hierarchy */ m->cgroup_root = mfree(m->cgroup_root); +#if 0 /// elogind is not init and must therefore search for PID 1 instead of self. r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &m->cgroup_root); +#else + r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &m->cgroup_root); +#endif // 0 if (r < 0) return log_error_errno(r, "Cannot determine cgroup we are running in: %m"); @@ -1789,30 +1807,35 @@ int manager_setup_cgroup(Manager *m) { if (r < 0) return log_error_errno(r, "Cannot find cgroup mount point: %m"); - 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"); + r = cg_unified_flush(); + if (r < 0) + return log_error_errno(r, "Couldn't determine if we are running in the unified hierarchy: %m"); - if (all_unified > 0) + all_unified = cg_all_unified(); + if (r < 0) + return log_error_errno(r, "Couldn't determine whether we are in all unified mode: %m"); + if (r > 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); + else { + r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); + if (r < 0) + return log_error_errno(r, "Failed to determine whether systemd's own controller is in unified mode: %m"); + if (r > 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_LEGACY ". File system hierarchy is at %s.", path); + } if (!m->test_run) { const char *scope_path; +#if 0 /// elogind is not init, and does not install the agent here. /* 3. Install agent */ - if (systemd_unified) { + if (cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) > 0) { /* In the unified hierarchy we can get * cgroup empty notifications via inotify. */ -#if 0 /// elogind does not support the unified hierarchy, yet. m->cgroup_inotify_event_source = sd_event_source_unref(m->cgroup_inotify_event_source); safe_close(m->cgroup_inotify_fd); @@ -1832,9 +1855,6 @@ int manager_setup_cgroup(Manager *m) { (void) sd_event_source_set_description(m->cgroup_inotify_event_source, "cgroup-inotify"); -#else - return log_error_errno(EOPNOTSUPP, "Unified cgroup hierarchy not supported: %m"); -#endif // 0 } else if (MANAGER_IS_SYSTEM(m)) { /* On the legacy hierarchy we only get @@ -1852,12 +1872,17 @@ int manager_setup_cgroup(Manager *m) { log_debug("Release agent already installed."); } -#if 0 /// elogind is not meant to run in systemd init scope /* 4. Make sure we are in the special "init.scope" unit in the root slice. */ scope_path = strjoina(m->cgroup_root, "/" SPECIAL_INIT_SCOPE); r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, scope_path, 0); #else - if (streq(SYSTEMD_CGROUP_CONTROLLER, "name=elogind")) + /* Note: + * This method is in core, and normally called by systemd + * being init. As elogind is never init, we can not install + * our agent here. We do so when mounting our cgroup file + * system, so only if elogind is its own tiny controller. + * Further, elogind is not meant to run in systemd init scope. */ + if (MANAGER_IS_SYSTEM(m)) // we are our own cgroup controller scope_path = strjoina(""); else if (streq(m->cgroup_root, "/elogind")) @@ -1872,11 +1897,13 @@ int manager_setup_cgroup(Manager *m) { return log_error_errno(r, "Failed to create %s control group: %m", scope_path); log_debug_elogind("Created control group \"%s\"", scope_path); +#if 0 /// elogind is not a "sub-controller" like systemd, so migration is not needed. /* also, move all other userspace processes remaining * in the root cgroup into that scope. */ r = cg_migrate(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, SYSTEMD_CGROUP_CONTROLLER, scope_path, 0); if (r < 0) log_warning_errno(r, "Couldn't move remaining userspace processes, ignoring: %m"); +#endif // 0 /* 5. And pin it, so that it cannot be unmounted */ safe_close(m->pin_cgroupfs_fd); @@ -2036,10 +2063,13 @@ int unit_get_memory_current(Unit *u, uint64_t *ret) { if ((u->cgroup_realized_mask & CGROUP_MASK_MEMORY) == 0) return -ENODATA; - if (cg_all_unified() <= 0) - r = cg_get_attribute("memory", u->cgroup_path, "memory.usage_in_bytes", &v); - else + r = cg_all_unified(); + if (r < 0) + return r; + if (r > 0) r = cg_get_attribute("memory", u->cgroup_path, "memory.current", &v); + else + r = cg_get_attribute("memory", u->cgroup_path, "memory.usage_in_bytes", &v); if (r == -ENOENT) return -ENODATA; if (r < 0) @@ -2081,7 +2111,10 @@ static int unit_get_cpu_usage_raw(Unit *u, nsec_t *ret) { if (!u->cgroup_path) return -ENODATA; - if (cg_all_unified() > 0) { + r = cg_all_unified(); + if (r < 0) + return r; + if (r > 0) { const char *keys[] = { "usage_usec", NULL }; _cleanup_free_ char *val = NULL; uint64_t us;