chiark / gitweb /
tmpfiles: Don't clean /var/lock/subsys; it is not aged content
[elogind.git] / src / cgroup-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <errno.h>
23 #include <unistd.h>
24 #include <signal.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <dirent.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30
31 #include "cgroup-util.h"
32 #include "log.h"
33 #include "set.h"
34 #include "macro.h"
35 #include "util.h"
36
37 int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
38         char *fs;
39         int r;
40         FILE *f;
41
42         assert(controller);
43         assert(path);
44         assert(_f);
45
46         if ((r = cg_get_path(controller, path, "cgroup.procs", &fs)) < 0)
47                 return r;
48
49         f = fopen(fs, "re");
50         free(fs);
51
52         if (!f)
53                 return -errno;
54
55         *_f = f;
56         return 0;
57 }
58
59 int cg_enumerate_tasks(const char *controller, const char *path, FILE **_f) {
60         char *fs;
61         int r;
62         FILE *f;
63
64         assert(controller);
65         assert(path);
66         assert(_f);
67
68         if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
69                 return r;
70
71         f = fopen(fs, "re");
72         free(fs);
73
74         if (!f)
75                 return -errno;
76
77         *_f = f;
78         return 0;
79 }
80
81 int cg_read_pid(FILE *f, pid_t *_pid) {
82         unsigned long ul;
83
84         /* Note that the cgroup.procs might contain duplicates! See
85          * cgroups.txt for details. */
86
87         errno = 0;
88         if (fscanf(f, "%lu", &ul) != 1) {
89
90                 if (feof(f))
91                         return 0;
92
93                 return errno ? -errno : -EIO;
94         }
95
96         if (ul <= 0)
97                 return -EIO;
98
99         *_pid = (pid_t) ul;
100         return 1;
101 }
102
103 int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d) {
104         char *fs;
105         int r;
106         DIR *d;
107
108         assert(controller);
109         assert(path);
110         assert(_d);
111
112         /* This is not recursive! */
113
114         if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
115                 return r;
116
117         d = opendir(fs);
118         free(fs);
119
120         if (!d)
121                 return -errno;
122
123         *_d = d;
124         return 0;
125 }
126
127 int cg_read_subgroup(DIR *d, char **fn) {
128         struct dirent *de;
129
130         assert(d);
131
132         errno = 0;
133         while ((de = readdir(d))) {
134                 char *b;
135
136                 if (de->d_type != DT_DIR)
137                         continue;
138
139                 if (streq(de->d_name, ".") ||
140                     streq(de->d_name, ".."))
141                         continue;
142
143                 if (!(b = strdup(de->d_name)))
144                         return -ENOMEM;
145
146                 *fn = b;
147                 return 1;
148         }
149
150         if (errno)
151                 return -errno;
152
153         return 0;
154 }
155
156 int cg_rmdir(const char *controller, const char *path) {
157         char *p;
158         int r;
159
160         if ((r = cg_get_path(controller, path, NULL, &p)) < 0)
161                 return r;
162
163         r = rmdir(p);
164         free(p);
165
166         return r < 0 ? -errno : 0;
167 }
168
169 int cg_kill(const char *controller, const char *path, int sig, bool ignore_self, Set *s) {
170         bool done = false;
171         int r, ret = 0;
172         pid_t my_pid;
173         FILE *f = NULL;
174         Set *allocated_set = NULL;
175
176         assert(controller);
177         assert(path);
178         assert(sig >= 0);
179
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 */
183
184         if (!s)
185                 if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func)))
186                         return -ENOMEM;
187
188         my_pid = getpid();
189
190         do {
191                 pid_t pid;
192                 done = true;
193
194                 if ((r = cg_enumerate_processes(controller, path, &f)) < 0) {
195                         if (ret >= 0 && r != -ENOENT)
196                                 ret = r;
197
198                         goto finish;
199                 }
200
201                 while ((r = cg_read_pid(f, &pid)) > 0) {
202
203                         if (pid == my_pid && ignore_self)
204                                 continue;
205
206                         if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
207                                 continue;
208
209                         /* If we haven't killed this process yet, kill
210                          * it */
211                         if (kill(pid, sig) < 0) {
212                                 if (ret >= 0 && errno != ESRCH)
213                                         ret = -errno;
214                         } else if (ret == 0)
215                                 ret = 1;
216
217                         done = false;
218
219                         if ((r = set_put(s, LONG_TO_PTR(pid))) < 0) {
220                                 if (ret >= 0)
221                                         ret = r;
222
223                                 goto finish;
224                         }
225                 }
226
227                 if (r < 0) {
228                         if (ret >= 0)
229                                 ret = r;
230
231                         goto finish;
232                 }
233
234                 fclose(f);
235                 f = NULL;
236
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. */
240
241         } while (!done);
242
243 finish:
244         if (allocated_set)
245                 set_free(allocated_set);
246
247         if (f)
248                 fclose(f);
249
250         return ret;
251 }
252
253 int cg_kill_recursive(const char *controller, const char *path, int sig, bool ignore_self, bool rem, Set *s) {
254         int r, ret = 0;
255         DIR *d = NULL;
256         char *fn;
257         Set *allocated_set = NULL;
258
259         assert(path);
260         assert(controller);
261         assert(sig >= 0);
262
263         if (!s)
264                 if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func)))
265                         return -ENOMEM;
266
267         ret = cg_kill(controller, path, sig, ignore_self, s);
268
269         if ((r = cg_enumerate_subgroups(controller, path, &d)) < 0) {
270                 if (ret >= 0 && r != -ENOENT)
271                         ret = r;
272
273                 goto finish;
274         }
275
276         while ((r = cg_read_subgroup(d, &fn)) > 0) {
277                 char *p = NULL;
278
279                 r = asprintf(&p, "%s/%s", path, fn);
280                 free(fn);
281
282                 if (r < 0) {
283                         if (ret >= 0)
284                                 ret = -ENOMEM;
285
286                         goto finish;
287                 }
288
289                 r = cg_kill_recursive(controller, p, sig, ignore_self, rem, s);
290                 free(p);
291
292                 if (r != 0 && ret >= 0)
293                         ret = r;
294         }
295
296         if (r < 0 && ret >= 0)
297                 ret = r;
298
299         if (rem)
300                 if ((r = cg_rmdir(controller, path)) < 0) {
301                         if (ret >= 0 && r != -ENOENT)
302                                 ret = r;
303                 }
304
305 finish:
306         if (d)
307                 closedir(d);
308
309         if (allocated_set)
310                 set_free(allocated_set);
311
312         return ret;
313 }
314
315 int cg_kill_recursive_and_wait(const char *controller, const char *path, bool rem) {
316         unsigned i;
317
318         assert(path);
319         assert(controller);
320
321         /* This safely kills all processes; first it sends a SIGTERM,
322          * then checks 8 times after 50ms whether the group is
323          * now empty, and finally kills everything that is left with
324          * SIGKILL */
325
326         for (i = 0; i < 10; i++) {
327                 int sig, r;
328
329                 if (i <= 0)
330                         sig = SIGTERM;
331                 else if (i >= 9)
332                         sig = SIGKILL;
333                 else
334                         sig = 0;
335
336                 if ((r = cg_kill_recursive(controller, path, sig, true, rem, NULL)) <= 0)
337                         return r;
338
339                 usleep(50 * USEC_PER_MSEC);
340         }
341
342         return 0;
343 }
344
345 int cg_migrate(const char *controller, const char *from, const char *to, bool ignore_self) {
346         bool done = false;
347         Set *s;
348         int r, ret = 0;
349         pid_t my_pid;
350         FILE *f = NULL;
351
352         assert(controller);
353         assert(from);
354         assert(to);
355
356         if (!(s = set_new(trivial_hash_func, trivial_compare_func)))
357                 return -ENOMEM;
358
359         my_pid = getpid();
360
361         do {
362                 pid_t pid;
363                 done = true;
364
365                 if ((r = cg_enumerate_tasks(controller, from, &f)) < 0) {
366                         if (ret >= 0 && r != -ENOENT)
367                                 ret = r;
368
369                         goto finish;
370                 }
371
372                 while ((r = cg_read_pid(f, &pid)) > 0) {
373
374                         /* This might do weird stuff if we aren't a
375                          * single-threaded program. However, we
376                          * luckily know we are not */
377                         if (pid == my_pid && ignore_self)
378                                 continue;
379
380                         if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
381                                 continue;
382
383                         if ((r = cg_attach(controller, to, pid)) < 0) {
384                                 if (ret >= 0 && r != -ESRCH)
385                                         ret = r;
386                         } else if (ret == 0)
387                                 ret = 1;
388
389                         done = false;
390
391                         if ((r = set_put(s, LONG_TO_PTR(pid))) < 0) {
392                                 if (ret >= 0)
393                                         ret = r;
394
395                                 goto finish;
396                         }
397                 }
398
399                 if (r < 0) {
400                         if (ret >= 0)
401                                 ret = r;
402
403                         goto finish;
404                 }
405
406                 fclose(f);
407                 f = NULL;
408
409         } while (!done);
410
411 finish:
412         set_free(s);
413
414         if (f)
415                 fclose(f);
416
417         return ret;
418 }
419
420 int cg_migrate_recursive(const char *controller, const char *from, const char *to, bool ignore_self, bool rem) {
421         int r, ret = 0;
422         DIR *d = NULL;
423         char *fn;
424
425         assert(controller);
426         assert(from);
427         assert(to);
428
429         ret = cg_migrate(controller, from, to, ignore_self);
430
431         if ((r = cg_enumerate_subgroups(controller, from, &d)) < 0) {
432                 if (ret >= 0 && r != -ENOENT)
433                         ret = r;
434                 goto finish;
435         }
436
437         while ((r = cg_read_subgroup(d, &fn)) > 0) {
438                 char *p = NULL;
439
440                 r = asprintf(&p, "%s/%s", from, fn);
441                 free(fn);
442
443                 if (r < 0) {
444                         if (ret >= 0)
445                                 ret = -ENOMEM;
446
447                         goto finish;
448                 }
449
450                 r = cg_migrate_recursive(controller, p, to, ignore_self, rem);
451                 free(p);
452
453                 if (r != 0 && ret >= 0)
454                         ret = r;
455         }
456
457         if (r < 0 && ret >= 0)
458                 ret = r;
459
460         if (rem)
461                 if ((r = cg_rmdir(controller, from)) < 0) {
462                         if (ret >= 0 && r != -ENOENT)
463                                 ret = r;
464                 }
465
466 finish:
467         if (d)
468                 closedir(d);
469
470         return ret;
471 }
472
473 int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) {
474         const char *p;
475         char *mp;
476         int r;
477
478         assert(controller);
479         assert(fs);
480
481         /* This is a very minimal lookup from controller names to
482          * paths. Since we have mounted most hierarchies ourselves
483          * should be kinda safe, but eventually we might want to
484          * extend this to have a fallback to actually check
485          * /proc/mounts. Might need caching then. */
486
487         if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
488                 p = "systemd";
489         else if (startswith(controller, "name="))
490                 p = controller + 5;
491         else
492                 p = controller;
493
494         if (asprintf(&mp, "/sys/fs/cgroup/%s", p) < 0)
495                 return -ENOMEM;
496
497         if ((r = path_is_mount_point(mp)) <= 0) {
498                 free(mp);
499                 return r < 0 ? r : -ENOENT;
500         }
501
502         if (path && suffix)
503                 r = asprintf(fs, "%s/%s/%s", mp, path, suffix);
504         else if (path)
505                 r = asprintf(fs, "%s/%s", mp, path);
506         else if (suffix)
507                 r = asprintf(fs, "%s/%s", mp, suffix);
508         else {
509                 path_kill_slashes(mp);
510                 *fs = mp;
511                 return 0;
512         }
513
514         free(mp);
515         path_kill_slashes(*fs);
516         return r < 0 ? -ENOMEM : 0;
517 }
518
519 int cg_trim(const char *controller, const char *path, bool delete_root) {
520         char *fs;
521         int r;
522
523         assert(controller);
524         assert(path);
525
526         if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
527                 return r;
528
529         r = rm_rf(fs, true, delete_root);
530         free(fs);
531
532         return r == -ENOENT ? 0 : r;
533 }
534
535 int cg_delete(const char *controller, const char *path) {
536         char *parent;
537         int r;
538
539         assert(controller);
540         assert(path);
541
542         if ((r = parent_of_path(path, &parent)) < 0)
543                 return r;
544
545         r = cg_migrate_recursive(controller, path, parent, false, true);
546         free(parent);
547
548         return r == -ENOENT ? 0 : r;
549 }
550
551 int cg_create(const char *controller, const char *path) {
552         char *fs;
553         int r;
554
555         assert(controller);
556         assert(path);
557
558         if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
559                 return r;
560
561         r = mkdir_parents(fs, 0755);
562
563         if (r >= 0) {
564                 if (mkdir(fs, 0755) >= 0)
565                         r = 1;
566                 else if (errno == EEXIST)
567                         r = 0;
568                 else
569                         r = -errno;
570         }
571
572         free(fs);
573
574         return r;
575 }
576
577 int cg_attach(const char *controller, const char *path, pid_t pid) {
578         char *fs;
579         int r;
580         char c[32];
581
582         assert(controller);
583         assert(path);
584         assert(pid >= 0);
585
586         if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
587                 return r;
588
589         if (pid == 0)
590                 pid = getpid();
591
592         snprintf(c, sizeof(c), "%lu\n", (unsigned long) pid);
593         char_array_0(c);
594
595         r = write_one_line_file(fs, c);
596         free(fs);
597
598         return r;
599 }
600
601 int cg_create_and_attach(const char *controller, const char *path, pid_t pid) {
602         int r, q;
603
604         assert(controller);
605         assert(path);
606         assert(pid >= 0);
607
608         if ((r = cg_create(controller, path)) < 0)
609                 return r;
610
611         if ((q = cg_attach(controller, path, pid)) < 0)
612                 return q;
613
614         /* This does not remove the cgroup on failure */
615
616         return r;
617 }
618
619 int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) {
620         char *fs;
621         int r;
622
623         assert(controller);
624         assert(path);
625
626         if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
627                 return r;
628
629         r = chmod_and_chown(fs, mode, uid, gid);
630         free(fs);
631
632         return r;
633 }
634
635 int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) {
636         char *fs;
637         int r;
638
639         assert(controller);
640         assert(path);
641
642         if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
643                 return r;
644
645         r = chmod_and_chown(fs, mode, uid, gid);
646         free(fs);
647
648         return r;
649 }
650
651 int cg_get_by_pid(const char *controller, pid_t pid, char **path) {
652         int r;
653         char *p = NULL;
654         FILE *f;
655         char *fs;
656         size_t cs;
657
658         assert(controller);
659         assert(path);
660         assert(pid >= 0);
661
662         if (pid == 0)
663                 pid = getpid();
664
665         if (asprintf(&fs, "/proc/%lu/cgroup", (unsigned long) pid) < 0)
666                 return -ENOMEM;
667
668         f = fopen(fs, "re");
669         free(fs);
670
671         if (!f)
672                 return errno == ENOENT ? -ESRCH : -errno;
673
674         cs = strlen(controller);
675
676         while (!feof(f)) {
677                 char line[LINE_MAX];
678                 char *l;
679
680                 errno = 0;
681                 if (!(fgets(line, sizeof(line), f))) {
682                         if (feof(f))
683                                 break;
684
685                         r = errno ? -errno : -EIO;
686                         goto finish;
687                 }
688
689                 truncate_nl(line);
690
691                 if (!(l = strchr(line, ':')))
692                         continue;
693
694                 l++;
695                 if (strncmp(l, controller, cs) != 0)
696                         continue;
697
698                 if (l[cs] != ':')
699                         continue;
700
701                 if (!(p = strdup(l + cs + 1))) {
702                         r = -ENOMEM;
703                         goto finish;
704                 }
705
706                 *path = p;
707                 r = 0;
708                 goto finish;
709         }
710
711         r = -ENOENT;
712
713 finish:
714         fclose(f);
715
716         return r;
717 }
718
719 int cg_install_release_agent(const char *controller, const char *agent) {
720         char *fs = NULL, *contents = NULL, *line = NULL, *sc;
721         int r;
722
723         assert(controller);
724         assert(agent);
725
726         if ((r = cg_get_path(controller, NULL, "release_agent", &fs)) < 0)
727                 return r;
728
729         if ((r = read_one_line_file(fs, &contents)) < 0)
730                 goto finish;
731
732         sc = strstrip(contents);
733         if (sc[0] == 0) {
734
735                 if (asprintf(&line, "%s\n", agent) < 0) {
736                         r = -ENOMEM;
737                         goto finish;
738                 }
739
740                 if ((r = write_one_line_file(fs, line)) < 0)
741                         goto finish;
742
743         } else if (!streq(sc, agent)) {
744                 r = -EEXIST;
745                 goto finish;
746         }
747
748         free(fs);
749         fs = NULL;
750         if ((r = cg_get_path(controller, NULL, "notify_on_release", &fs)) < 0)
751                 goto finish;
752
753         free(contents);
754         contents = NULL;
755         if ((r = read_one_line_file(fs, &contents)) < 0)
756                 goto finish;
757
758         sc = strstrip(contents);
759
760         if (streq(sc, "0")) {
761                 if ((r = write_one_line_file(fs, "1\n")) < 0)
762                         goto finish;
763
764                 r = 1;
765         } else if (!streq(sc, "1")) {
766                 r = -EIO;
767                 goto finish;
768         } else
769                 r = 0;
770
771 finish:
772         free(fs);
773         free(contents);
774         free(line);
775
776         return r;
777 }
778
779 int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
780         pid_t pid;
781         int r;
782         FILE *f;
783         bool found = false;
784
785         assert(controller);
786         assert(path);
787
788         if ((r = cg_enumerate_tasks(controller, path, &f)) < 0)
789                 return r == -ENOENT ? 1 : r;
790
791         while ((r = cg_read_pid(f, &pid)) > 0) {
792
793                 if (ignore_self && pid == getpid())
794                         continue;
795
796                 found = true;
797                 break;
798         }
799
800         fclose(f);
801
802         if (r < 0)
803                 return r;
804
805         return !found;
806 }
807
808 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
809         int r;
810         DIR *d = NULL;
811         char *fn;
812
813         assert(controller);
814         assert(path);
815
816         if ((r = cg_is_empty(controller, path, ignore_self)) <= 0)
817                 return r;
818
819         if ((r = cg_enumerate_subgroups(controller, path, &d)) < 0)
820                 return r == -ENOENT ? 1 : r;
821
822         while ((r = cg_read_subgroup(d, &fn)) > 0) {
823                 char *p = NULL;
824
825                 r = asprintf(&p, "%s/%s", path, fn);
826                 free(fn);
827
828                 if (r < 0) {
829                         r = -ENOMEM;
830                         goto finish;
831                 }
832
833                 r = cg_is_empty_recursive(controller, p, ignore_self);
834                 free(p);
835
836                 if (r <= 0)
837                         goto finish;
838         }
839
840         if (r >= 0)
841                 r = 1;
842
843 finish:
844
845         if (d)
846                 closedir(d);
847
848         return r;
849 }
850
851 int cg_split_spec(const char *spec, char **controller, char **path) {
852         const char *e;
853         char *t = NULL, *u = NULL;
854
855         assert(spec);
856         assert(controller || path);
857
858         if (*spec == '/') {
859
860                 if (path) {
861                         if (!(t = strdup(spec)))
862                                 return -ENOMEM;
863
864                         *path = t;
865                 }
866
867                 if (controller)
868                         *controller = NULL;
869
870                 return 0;
871         }
872
873         if (!(e = strchr(spec, ':'))) {
874
875                 if (strchr(spec, '/') || spec[0] == 0)
876                         return -EINVAL;
877
878                 if (controller) {
879                         if (!(t = strdup(spec)))
880                                 return -ENOMEM;
881
882                         *controller = t;
883                 }
884
885                 if (path)
886                         *path = NULL;
887
888                 return 0;
889         }
890
891         if (e[1] != '/' ||
892             e == spec ||
893             memchr(spec, '/', e-spec))
894                 return -EINVAL;
895
896         if (controller)
897                 if (!(t = strndup(spec, e-spec)))
898                         return -ENOMEM;
899
900         if (path)
901                 if (!(u = strdup(e+1))) {
902                         free(t);
903                         return -ENOMEM;
904                 }
905
906         if (controller)
907                 *controller = t;
908
909         if (path)
910                 *path = u;
911
912         return 0;
913 }
914
915 int cg_join_spec(const char *controller, const char *path, char **spec) {
916         assert(controller);
917         assert(path);
918
919         if (!path_is_absolute(path) ||
920             controller[0] == 0 ||
921             strchr(controller, ':') ||
922             strchr(controller, '/'))
923                 return -EINVAL;
924
925         if (asprintf(spec, "%s:%s", controller, path) < 0)
926                 return -ENOMEM;
927
928         return 0;
929 }
930
931 int cg_fix_path(const char *path, char **result) {
932         char *t, *c, *p;
933         int r;
934
935         assert(path);
936         assert(result);
937
938         /* First check if it already is a filesystem path */
939         if (path_is_absolute(path) &&
940             path_startswith(path, "/sys/fs/cgroup") &&
941             access(path, F_OK) >= 0) {
942
943                 if (!(t = strdup(path)))
944                         return -ENOMEM;
945
946                 *result = t;
947                 return 0;
948         }
949
950         /* Otherwise treat it as cg spec */
951         if ((r = cg_split_spec(path, &c, &p)) < 0)
952                 return r;
953
954         r = cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
955         free(c);
956         free(p);
957
958         return r;
959 }