1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
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/>.
29 #include <sys/types.h>
31 #include "cgroup-util.h"
37 int cg_enumerate_processes(const char *controller
, const char *path
, FILE **_f
) {
46 if ((r
= cg_get_path(controller
, path
, "cgroup.procs", &fs
)) < 0)
59 int cg_enumerate_tasks(const char *controller
, const char *path
, FILE **_f
) {
68 if ((r
= cg_get_path(controller
, path
, "tasks", &fs
)) < 0)
81 int cg_read_pid(FILE *f
, pid_t
*_pid
) {
84 /* Note that the cgroup.procs might contain duplicates! See
85 * cgroups.txt for details. */
88 if (fscanf(f
, "%lu", &ul
) != 1) {
93 return errno
? -errno
: -EIO
;
103 int cg_enumerate_subgroups(const char *controller
, const char *path
, DIR **_d
) {
112 /* This is not recursive! */
114 if ((r
= cg_get_path(controller
, path
, NULL
, &fs
)) < 0)
127 int cg_read_subgroup(DIR *d
, char **fn
) {
133 while ((de
= readdir(d
))) {
136 if (de
->d_type
!= DT_DIR
)
139 if (streq(de
->d_name
, ".") ||
140 streq(de
->d_name
, ".."))
143 if (!(b
= strdup(de
->d_name
)))
156 int cg_rmdir(const char *controller
, const char *path
) {
160 if ((r
= cg_get_path(controller
, path
, NULL
, &p
)) < 0)
166 return r
< 0 ? -errno
: 0;
169 int cg_kill(const char *controller
, const char *path
, int sig
, bool ignore_self
, Set
*s
) {
174 Set
*allocated_set
= NULL
;
180 /* This goes through the tasks list and kills them all. This
181 * is repeated until no further processes are added to the
182 * tasks list, to properly handle forking processes */
185 if (!(s
= allocated_set
= set_new(trivial_hash_func
, trivial_compare_func
)))
194 if ((r
= cg_enumerate_processes(controller
, path
, &f
)) < 0) {
195 if (ret
>= 0 && r
!= -ENOENT
)
201 while ((r
= cg_read_pid(f
, &pid
)) > 0) {
203 if (pid
== my_pid
&& ignore_self
)
206 if (set_get(s
, LONG_TO_PTR(pid
)) == LONG_TO_PTR(pid
))
209 /* If we haven't killed this process yet, kill
211 if (kill(pid
, sig
) < 0) {
212 if (ret
>= 0 && errno
!= ESRCH
)
219 if ((r
= set_put(s
, LONG_TO_PTR(pid
))) < 0) {
237 /* To avoid racing against processes which fork
238 * quicker than we can kill them we repeat this until
239 * no new pids need to be killed. */
245 set_free(allocated_set
);
253 int cg_kill_recursive(const char *controller
, const char *path
, int sig
, bool ignore_self
, bool rem
, Set
*s
) {
257 Set
*allocated_set
= NULL
;
264 if (!(s
= allocated_set
= set_new(trivial_hash_func
, trivial_compare_func
)))
267 ret
= cg_kill(controller
, path
, sig
, ignore_self
, s
);
269 if ((r
= cg_enumerate_subgroups(controller
, path
, &d
)) < 0) {
270 if (ret
>= 0 && r
!= -ENOENT
)
276 while ((r
= cg_read_subgroup(d
, &fn
)) > 0) {
279 r
= asprintf(&p
, "%s/%s", path
, fn
);
289 r
= cg_kill_recursive(controller
, p
, sig
, ignore_self
, rem
, s
);
292 if (r
!= 0 && ret
>= 0)
296 if (r
< 0 && ret
>= 0)
300 if ((r
= cg_rmdir(controller
, path
)) < 0) {
312 set_free(allocated_set
);
317 int cg_kill_recursive_and_wait(const char *controller
, const char *path
, bool rem
) {
323 /* This safely kills all processes; first it sends a SIGTERM,
324 * then checks 8 times after 200ms whether the group is now
325 * empty, then kills everything that is left with SIGKILL and
326 * finally checks 5 times after 200ms each whether the group
327 * is finally empty. */
329 for (i
= 0; i
< 15; i
++) {
339 if ((r
= cg_kill_recursive(controller
, path
, sig
, true, rem
, NULL
)) <= 0)
342 usleep(200 * USEC_PER_MSEC
);
348 int cg_migrate(const char *controller
, const char *from
, const char *to
, bool ignore_self
) {
359 if (!(s
= set_new(trivial_hash_func
, trivial_compare_func
)))
368 if ((r
= cg_enumerate_tasks(controller
, from
, &f
)) < 0) {
369 if (ret
>= 0 && r
!= -ENOENT
)
375 while ((r
= cg_read_pid(f
, &pid
)) > 0) {
377 /* This might do weird stuff if we aren't a
378 * single-threaded program. However, we
379 * luckily know we are not */
380 if (pid
== my_pid
&& ignore_self
)
383 if (set_get(s
, LONG_TO_PTR(pid
)) == LONG_TO_PTR(pid
))
386 if ((r
= cg_attach(controller
, to
, pid
)) < 0) {
387 if (ret
>= 0 && r
!= -ESRCH
)
394 if ((r
= set_put(s
, LONG_TO_PTR(pid
))) < 0) {
423 int cg_migrate_recursive(const char *controller
, const char *from
, const char *to
, bool ignore_self
, bool rem
) {
432 ret
= cg_migrate(controller
, from
, to
, ignore_self
);
434 if ((r
= cg_enumerate_subgroups(controller
, from
, &d
)) < 0) {
435 if (ret
>= 0 && r
!= -ENOENT
)
440 while ((r
= cg_read_subgroup(d
, &fn
)) > 0) {
443 r
= asprintf(&p
, "%s/%s", from
, fn
);
453 r
= cg_migrate_recursive(controller
, p
, to
, ignore_self
, rem
);
456 if (r
!= 0 && ret
>= 0)
460 if (r
< 0 && ret
>= 0)
464 if ((r
= cg_rmdir(controller
, from
)) < 0) {
478 int cg_get_path(const char *controller
, const char *path
, const char *suffix
, char **fs
) {
486 /* This is a very minimal lookup from controller names to
487 * paths. Since we have mounted most hierarchies ourselves
488 * should be kinda safe, but eventually we might want to
489 * extend this to have a fallback to actually check
490 * /proc/mounts. Might need caching then. */
492 if (streq(controller
, SYSTEMD_CGROUP_CONTROLLER
))
494 else if (startswith(controller
, "name="))
499 if (asprintf(&mp
, "/sys/fs/cgroup/%s", p
) < 0)
502 if ((r
= path_is_mount_point(mp
)) <= 0) {
504 return r
< 0 ? r
: -ENOENT
;
508 r
= asprintf(fs
, "%s/%s/%s", mp
, path
, suffix
);
510 r
= asprintf(fs
, "%s/%s", mp
, path
);
512 r
= asprintf(fs
, "%s/%s", mp
, suffix
);
514 path_kill_slashes(mp
);
520 path_kill_slashes(*fs
);
521 return r
< 0 ? -ENOMEM
: 0;
524 int cg_trim(const char *controller
, const char *path
, bool delete_root
) {
531 if ((r
= cg_get_path(controller
, path
, NULL
, &fs
)) < 0)
534 r
= rm_rf(fs
, true, delete_root
);
537 return r
== -ENOENT
? 0 : r
;
540 int cg_delete(const char *controller
, const char *path
) {
547 if ((r
= parent_of_path(path
, &parent
)) < 0)
550 r
= cg_migrate_recursive(controller
, path
, parent
, false, true);
553 return r
== -ENOENT
? 0 : r
;
556 int cg_create(const char *controller
, const char *path
) {
563 if ((r
= cg_get_path(controller
, path
, NULL
, &fs
)) < 0)
566 r
= mkdir_parents(fs
, 0755);
569 if (mkdir(fs
, 0755) >= 0)
571 else if (errno
== EEXIST
)
582 int cg_attach(const char *controller
, const char *path
, pid_t pid
) {
591 if ((r
= cg_get_path(controller
, path
, "tasks", &fs
)) < 0)
597 snprintf(c
, sizeof(c
), "%lu\n", (unsigned long) pid
);
600 r
= write_one_line_file(fs
, c
);
606 int cg_create_and_attach(const char *controller
, const char *path
, pid_t pid
) {
613 if ((r
= cg_create(controller
, path
)) < 0)
616 if ((q
= cg_attach(controller
, path
, pid
)) < 0)
619 /* This does not remove the cgroup on failure */
624 int cg_set_group_access(const char *controller
, const char *path
, mode_t mode
, uid_t uid
, gid_t gid
) {
631 if ((r
= cg_get_path(controller
, path
, NULL
, &fs
)) < 0)
634 r
= chmod_and_chown(fs
, mode
, uid
, gid
);
640 int cg_set_task_access(const char *controller
, const char *path
, mode_t mode
, uid_t uid
, gid_t gid
) {
647 if ((r
= cg_get_path(controller
, path
, "tasks", &fs
)) < 0)
650 r
= chmod_and_chown(fs
, mode
, uid
, gid
);
656 int cg_get_by_pid(const char *controller
, pid_t pid
, char **path
) {
670 if (asprintf(&fs
, "/proc/%lu/cgroup", (unsigned long) pid
) < 0)
677 return errno
== ENOENT
? -ESRCH
: -errno
;
679 cs
= strlen(controller
);
686 if (!(fgets(line
, sizeof(line
), f
))) {
690 r
= errno
? -errno
: -EIO
;
696 if (!(l
= strchr(line
, ':')))
700 if (strncmp(l
, controller
, cs
) != 0)
706 if (!(p
= strdup(l
+ cs
+ 1))) {
724 int cg_install_release_agent(const char *controller
, const char *agent
) {
725 char *fs
= NULL
, *contents
= NULL
, *line
= NULL
, *sc
;
731 if ((r
= cg_get_path(controller
, NULL
, "release_agent", &fs
)) < 0)
734 if ((r
= read_one_line_file(fs
, &contents
)) < 0)
737 sc
= strstrip(contents
);
740 if (asprintf(&line
, "%s\n", agent
) < 0) {
745 if ((r
= write_one_line_file(fs
, line
)) < 0)
748 } else if (!streq(sc
, agent
)) {
755 if ((r
= cg_get_path(controller
, NULL
, "notify_on_release", &fs
)) < 0)
760 if ((r
= read_one_line_file(fs
, &contents
)) < 0)
763 sc
= strstrip(contents
);
765 if (streq(sc
, "0")) {
766 if ((r
= write_one_line_file(fs
, "1\n")) < 0)
770 } else if (!streq(sc
, "1")) {
784 int cg_is_empty(const char *controller
, const char *path
, bool ignore_self
) {
793 if ((r
= cg_enumerate_tasks(controller
, path
, &f
)) < 0)
794 return r
== -ENOENT
? 1 : r
;
796 while ((r
= cg_read_pid(f
, &pid
)) > 0) {
798 if (ignore_self
&& pid
== getpid())
813 int cg_is_empty_recursive(const char *controller
, const char *path
, bool ignore_self
) {
821 if ((r
= cg_is_empty(controller
, path
, ignore_self
)) <= 0)
824 if ((r
= cg_enumerate_subgroups(controller
, path
, &d
)) < 0)
825 return r
== -ENOENT
? 1 : r
;
827 while ((r
= cg_read_subgroup(d
, &fn
)) > 0) {
830 r
= asprintf(&p
, "%s/%s", path
, fn
);
838 r
= cg_is_empty_recursive(controller
, p
, ignore_self
);
856 int cg_split_spec(const char *spec
, char **controller
, char **path
) {
858 char *t
= NULL
, *u
= NULL
;
861 assert(controller
|| path
);
866 if (!(t
= strdup(spec
)))
878 if (!(e
= strchr(spec
, ':'))) {
880 if (strchr(spec
, '/') || spec
[0] == 0)
884 if (!(t
= strdup(spec
)))
898 memchr(spec
, '/', e
-spec
))
902 if (!(t
= strndup(spec
, e
-spec
)))
906 if (!(u
= strdup(e
+1))) {
920 int cg_join_spec(const char *controller
, const char *path
, char **spec
) {
924 if (!path_is_absolute(path
) ||
925 controller
[0] == 0 ||
926 strchr(controller
, ':') ||
927 strchr(controller
, '/'))
930 if (asprintf(spec
, "%s:%s", controller
, path
) < 0)
936 int cg_fix_path(const char *path
, char **result
) {
943 /* First check if it already is a filesystem path */
944 if (path_is_absolute(path
) &&
945 path_startswith(path
, "/sys/fs/cgroup") &&
946 access(path
, F_OK
) >= 0) {
948 if (!(t
= strdup(path
)))
955 /* Otherwise treat it as cg spec */
956 if ((r
= cg_split_spec(path
, &c
, &p
)) < 0)
959 r
= cg_get_path(c
? c
: SYSTEMD_CGROUP_CONTROLLER
, p
? p
: "/", NULL
, result
);