1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include <libcgroup.h>
30 #include "cgroup-util.h"
37 Currently, the only remaining functionality from libcgroup we call
40 - cgroup_walk_tree_begin()/cgroup_walk_tree_next()
41 - cgroup_delete_cgroup_ext()
44 int cg_translate_error(int error, int _errno) {
48 case ECGROUPNOTCOMPILED:
49 case ECGROUPNOTMOUNTED:
51 case ECGROUPNOTCREATED:
57 case ECGROUPNOTALLOWED:
67 static struct cgroup* cg_new(const char *controller, const char *path) {
68 struct cgroup *cgroup;
73 if (!(cgroup = cgroup_new_cgroup(path)))
76 if (!cgroup_add_controller(cgroup, controller)) {
84 int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
93 if ((r = cg_get_path(controller, path, "cgroup.procs", &fs)) < 0)
106 int cg_enumerate_tasks(const char *controller, const char *path, FILE **_f) {
115 if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
128 int cg_read_pid(FILE *f, pid_t *_pid) {
131 /* Note that the cgroup.procs might contain duplicates! See
132 * cgroups.txt for details. */
135 if (fscanf(f, "%lu", &ul) != 1) {
140 return errno ? -errno : -EIO;
150 int cg_kill(const char *controller, const char *path, int sig, bool ignore_self) {
151 bool killed = false, done = false;
161 /* This goes through the tasks list and kills them all. This
162 * is repeated until no further processes are added to the
163 * tasks list, to properly handle forking processes */
165 if (!(s = set_new(trivial_hash_func, trivial_compare_func)))
174 if ((r = cg_enumerate_processes(controller, path, &f)) < 0)
177 while ((r = cg_read_pid(f, &pid)) > 0) {
179 if (pid == my_pid && ignore_self)
182 if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
185 /* If we haven't killed this process yet, kill
187 if (kill(pid, sig) < 0 && errno != ESRCH) {
195 if ((r = set_put(s, LONG_TO_PTR(pid))) < 0)
202 /* To avoid racing against processes which fork
203 * quicker than we can kill them we repeat this until
204 * no new pids need to be killed. */
206 } while (!done && r >= 0);
223 int cg_kill_recursive(const char *controller, const char *path, int sig, bool ignore_self) {
224 struct cgroup_file_info info;
225 int level = 0, r, ret = 0;
226 void *iterator = NULL;
235 r = cgroup_walk_tree_begin(controller, path, 0, &iterator, &info, &level);
240 if (info.type != CGROUP_FILE_TYPE_DIR)
243 if (asprintf(&p, "%s/%s", path, info.path) < 0) {
248 k = cg_kill(controller, p, sig, ignore_self);
259 r = cgroup_walk_tree_next(0, &iterator, &info, level);
263 if (r == 0 || r == ECGEOF)
265 else if (r == ECGOTHER && errno == ENOENT)
268 ret = cg_translate_error(r, errno);
271 assert_se(cgroup_walk_tree_end(&iterator) == 0);
276 int cg_kill_recursive_and_wait(const char *controller, const char *path) {
282 /* This safely kills all processes; first it sends a SIGTERM,
283 * then checks 8 times after 50ms whether the group is
284 * now empty, and finally kills everything that is left with
287 for (i = 0; i < 10; i++) {
297 if ((r = cg_kill_recursive(controller, path, sig, true)) <= 0)
300 usleep(50 * USEC_PER_MSEC);
306 int cg_migrate(const char *controller, const char *from, const char *to, bool ignore_self) {
307 bool migrated = false, done = false;
322 if ((r = cg_enumerate_tasks(controller, from, &f)) < 0)
325 while ((r = cg_read_pid(f, &pid)) > 0) {
327 if (pid == my_pid && ignore_self)
330 if ((r = cg_attach(controller, to, pid)) < 0) {
342 } while (!done && r >= 0);
358 int cg_migrate_recursive(const char *controller, const char *from, const char *to, bool ignore_self) {
359 struct cgroup_file_info info;
360 int level = 0, r, ret = 0;
361 void *iterator = NULL;
362 bool migrated = false;
370 r = cgroup_walk_tree_begin(controller, from, 0, &iterator, &info, &level);
375 if (info.type != CGROUP_FILE_TYPE_DIR)
378 if (asprintf(&p, "%s/%s", from, info.path) < 0) {
383 k = cg_migrate(controller, p, to, ignore_self);
393 r = cgroup_walk_tree_next(0, &iterator, &info, level);
397 if (r == 0 || r == ECGEOF)
399 else if (r == ECGOTHER && errno == ENOENT)
402 r = cg_translate_error(r, errno);
405 assert_se(cgroup_walk_tree_end(&iterator) == 0);
410 int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) {
418 /* This is a very minimal lookup from controller names to
419 * paths. Since we have mounted most hierarchies ourselves
420 * should be kinda safe, but eventually we might want to
421 * extend this to have a fallback to actually check
422 * /proc/mounts. Might need caching then. */
424 if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
426 else if (startswith(controller, "name="))
431 if (asprintf(&mp, "/cgroup/%s", p) < 0)
434 if ((r = path_is_mount_point(mp)) <= 0) {
436 return r < 0 ? r : -ENOENT;
440 r = asprintf(fs, "%s/%s/%s", mp, path, suffix);
442 r = asprintf(fs, "%s/%s", mp, path);
444 r = asprintf(fs, "%s/%s", mp, suffix);
446 path_kill_slashes(mp);
452 path_kill_slashes(*fs);
453 return r < 0 ? -ENOMEM : 0;
456 int cg_trim(const char *controller, const char *path, bool delete_root) {
463 if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
466 r = rm_rf(fs, true, delete_root);
472 int cg_delete(const char *controller, const char *path) {
479 if (!(cg = cg_new(controller, path)))
482 if ((r = cgroup_delete_cgroup_ext(cg, CGFLAG_DELETE_RECURSIVE|CGFLAG_DELETE_IGNORE_MIGRATION)) != 0) {
483 r = cg_translate_error(r, errno);
495 int cg_create(const char *controller, const char *path) {
502 if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
505 r = mkdir_p(fs, 0755);
511 int cg_attach(const char *controller, const char *path, pid_t pid) {
520 if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
526 snprintf(c, sizeof(c), "%lu\n", (unsigned long) pid);
529 r = write_one_line_file(fs, c);
535 int cg_create_and_attach(const char *controller, const char *path, pid_t pid) {
542 if ((r = cg_create(controller, path)) < 0)
545 if ((r = cg_attach(controller, path, pid)) < 0)
548 /* This does not remove the cgroup on failure */
553 int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) {
560 if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
563 r = chmod_and_chown(fs, mode, uid, gid);
569 int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) {
576 if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
579 r = chmod_and_chown(fs, mode, uid, gid);
585 int cg_get_by_pid(const char *controller, pid_t pid, char **path) {
599 if (asprintf(&fs, "/proc/%lu/cgroup", (unsigned long) pid) < 0)
605 cs = strlen(controller);
612 if (!(fgets(line, sizeof(line), f))) {
616 r = errno ? -errno : -EIO;
622 if (!(l = strchr(line, ':')))
626 if (strncmp(l, controller, cs) != 0)
632 if (!(p = strdup(l + cs + 1))) {
650 int cg_install_release_agent(const char *controller, const char *agent) {
651 char *fs = NULL, *contents = NULL, *line = NULL, *sc;
657 if ((r = cg_get_path(controller, NULL, "release_agent", &fs)) < 0)
660 if ((r = read_one_line_file(fs, &contents)) < 0)
663 sc = strstrip(contents);
666 if (asprintf(&line, "%s\n", agent) < 0) {
671 if ((r = write_one_line_file(fs, line)) < 0)
674 } else if (!streq(sc, agent)) {
681 if ((r = cg_get_path(controller, NULL, "notify_on_release", &fs)) < 0) {
688 if ((r = read_one_line_file(fs, &contents)) < 0)
691 sc = strstrip(contents);
693 if (streq(sc, "0")) {
694 if ((r = write_one_line_file(fs, "1\n")) < 0)
698 } else if (!streq(sc, "1")) {
712 int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
721 if ((r = cg_enumerate_tasks(controller, path, &f)) < 0)
724 while ((r = cg_read_pid(f, &pid)) > 0) {
726 if (ignore_self && pid == getpid())
741 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
742 struct cgroup_file_info info;
743 int level = 0, r, ret = 0;
744 void *iterator = NULL;
752 r = cgroup_walk_tree_begin(controller, path, 0, &iterator, &info, &level);
757 if (info.type != CGROUP_FILE_TYPE_DIR)
760 if (asprintf(&p, "%s/%s", path, info.path) < 0) {
765 k = cg_is_empty(controller, p, ignore_self);
777 r = cgroup_walk_tree_next(0, &iterator, &info, level);
781 if (r == 0 || r == ECGEOF)
783 else if (r == ECGOTHER && errno == ENOENT)
786 ret = cg_translate_error(r, errno);
789 assert_se(cgroup_walk_tree_end(&iterator) == 0);
797 if ((r = cgroup_init()) != 0)
798 return cg_translate_error(r, errno);