X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcgroup-util.c;h=ec48ea63b4d0db188c7ba247953d64f0cfa20b88;hp=b68b9ad3a33a20c9c85e2e0c7a5d495e3f7cb71a;hb=ad293f5a94d8124ece7d1cb860952a87b1c8d98f;hpb=0b1724894fb85aa1c07b2619e9269cfafd736956 diff --git a/src/cgroup-util.c b/src/cgroup-util.c index b68b9ad3a..ec48ea63b 100644 --- a/src/cgroup-util.c +++ b/src/cgroup-util.c @@ -153,20 +153,41 @@ int cg_read_subgroup(DIR *d, char **fn) { return 0; } -int cg_rmdir(const char *controller, const char *path) { +int cg_rmdir(const char *controller, const char *path, bool honour_sticky) { char *p; int r; - if ((r = cg_get_path(controller, path, NULL, &p)) < 0) + r = cg_get_path(controller, path, NULL, &p); + if (r < 0) return r; + if (honour_sticky) { + char *tasks; + + /* If the sticky bit is set don't remove the directory */ + + tasks = strappend(p, "/tasks"); + if (!tasks) { + free(p); + return -ENOMEM; + } + + r = file_is_sticky(tasks); + free(tasks); + + if (r > 0) { + free(p); + return 0; + } + } + r = rmdir(p); free(p); - return r < 0 ? -errno : 0; + return (r < 0 && errno != ENOENT) ? -errno : 0; } -int cg_kill(const char *controller, const char *path, int sig, bool ignore_self, Set *s) { +int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s) { bool done = false; int r, ret = 0; pid_t my_pid; @@ -211,8 +232,13 @@ int cg_kill(const char *controller, const char *path, int sig, bool ignore_self, if (kill(pid, sig) < 0) { if (ret >= 0 && errno != ESRCH) ret = -errno; - } else if (ret == 0) + } else if (ret == 0) { + + if (sigcont) + kill(pid, SIGCONT); + ret = 1; + } done = false; @@ -250,7 +276,7 @@ finish: return ret; } -int cg_kill_recursive(const char *controller, const char *path, int sig, bool ignore_self, bool rem, Set *s) { +int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool rem, Set *s) { int r, ret = 0; DIR *d = NULL; char *fn; @@ -264,7 +290,7 @@ int cg_kill_recursive(const char *controller, const char *path, int sig, bool ig if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func))) return -ENOMEM; - ret = cg_kill(controller, path, sig, ignore_self, s); + ret = cg_kill(controller, path, sig, sigcont, ignore_self, s); if ((r = cg_enumerate_subgroups(controller, path, &d)) < 0) { if (ret >= 0 && r != -ENOENT) @@ -286,7 +312,7 @@ int cg_kill_recursive(const char *controller, const char *path, int sig, bool ig goto finish; } - r = cg_kill_recursive(controller, p, sig, ignore_self, rem, s); + r = cg_kill_recursive(controller, p, sig, sigcont, ignore_self, rem, s); free(p); if (r != 0 && ret >= 0) @@ -297,7 +323,7 @@ int cg_kill_recursive(const char *controller, const char *path, int sig, bool ig ret = r; if (rem) - if ((r = cg_rmdir(controller, path)) < 0) { + if ((r = cg_rmdir(controller, path, true)) < 0) { if (ret >= 0 && r != -ENOENT && r != -EBUSY) @@ -336,7 +362,7 @@ int cg_kill_recursive_and_wait(const char *controller, const char *path, bool re else sig = 0; - if ((r = cg_kill_recursive(controller, path, sig, true, rem, NULL)) <= 0) + if ((r = cg_kill_recursive(controller, path, sig, true, true, rem, NULL)) <= 0) return r; usleep(200 * USEC_PER_MSEC); @@ -461,7 +487,7 @@ int cg_migrate_recursive(const char *controller, const char *from, const char *t ret = r; if (rem) - if ((r = cg_rmdir(controller, from)) < 0) { + if ((r = cg_rmdir(controller, from, true)) < 0) { if (ret >= 0 && r != -ENOENT && r != -EBUSY) @@ -477,12 +503,26 @@ finish: int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) { const char *p; - char *mp; - int r; + char *t; + static __thread bool good = false; assert(controller); assert(fs); + if (_unlikely_(!good)) { + int r; + + r = path_is_mount_point("/sys/fs/cgroup"); + if (r <= 0) + return r < 0 ? r : -ENOENT; + + /* Cache this to save a few stat()s */ + good = true; + } + + if (isempty(controller)) + return -EINVAL; + /* This is a very minimal lookup from controller names to * paths. Since we have mounted most hierarchies ourselves * should be kinda safe, but eventually we might want to @@ -496,29 +536,22 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch else p = controller; - if (asprintf(&mp, "/sys/fs/cgroup/%s", p) < 0) - return -ENOMEM; - - if ((r = path_is_mount_point(mp)) <= 0) { - free(mp); - return r < 0 ? r : -ENOENT; - } - if (path && suffix) - r = asprintf(fs, "%s/%s/%s", mp, path, suffix); + t = join("/sys/fs/cgroup/", p, "/", path, "/", suffix, NULL); else if (path) - r = asprintf(fs, "%s/%s", mp, path); + t = join("/sys/fs/cgroup/", p, "/", path, NULL); else if (suffix) - r = asprintf(fs, "%s/%s", mp, suffix); - else { - path_kill_slashes(mp); - *fs = mp; - return 0; - } + t = join("/sys/fs/cgroup/", p, "/", suffix, NULL); + else + t = join("/sys/fs/cgroup/", p, NULL); + + if (!t) + return -ENOMEM; - free(mp); - path_kill_slashes(*fs); - return r < 0 ? -ENOMEM : 0; + path_kill_slashes(t); + + *fs = t; + return 0; } int cg_trim(const char *controller, const char *path, bool delete_root) { @@ -531,7 +564,7 @@ int cg_trim(const char *controller, const char *path, bool delete_root) { if ((r = cg_get_path(controller, path, NULL, &fs)) < 0) return r; - r = rm_rf(fs, true, delete_root); + r = rm_rf(fs, true, delete_root, true); free(fs); return r == -ENOENT ? 0 : r; @@ -962,3 +995,31 @@ int cg_fix_path(const char *path, char **result) { return r; } + +int cg_get_user_path(char **path) { + char *root, *p; + + assert(path); + + /* Figure out the place to put user cgroups below. We use the + * same as PID 1 has but with the "/system" suffix replaced by + * "/user" */ + + if (cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &root) < 0) + p = strdup("/user"); + else { + if (endswith(root, "/system")) + root[strlen(root) - 7] = 0; + else if (streq(root, "/")) + root[0] = 0; + + p = strappend(root, "/user"); + free(root); + } + + if (!p) + return -ENOMEM; + + *path = p; + return 0; +}