chiark / gitweb /
s/seperate/separate/
[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 sigcont, 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 = 0;
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
216                                 if (sigcont)
217                                         kill(pid, SIGCONT);
218
219                                 ret = 1;
220                         }
221
222                         done = false;
223
224                         if ((r = set_put(s, LONG_TO_PTR(pid))) < 0) {
225                                 if (ret >= 0)
226                                         ret = r;
227
228                                 goto finish;
229                         }
230                 }
231
232                 if (r < 0) {
233                         if (ret >= 0)
234                                 ret = r;
235
236                         goto finish;
237                 }
238
239                 fclose(f);
240                 f = NULL;
241
242                 /* To avoid racing against processes which fork
243                  * quicker than we can kill them we repeat this until
244                  * no new pids need to be killed. */
245
246         } while (!done);
247
248 finish:
249         if (allocated_set)
250                 set_free(allocated_set);
251
252         if (f)
253                 fclose(f);
254
255         return ret;
256 }
257
258 int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool rem, Set *s) {
259         int r, ret = 0;
260         DIR *d = NULL;
261         char *fn;
262         Set *allocated_set = NULL;
263
264         assert(path);
265         assert(controller);
266         assert(sig >= 0);
267
268         if (!s)
269                 if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func)))
270                         return -ENOMEM;
271
272         ret = cg_kill(controller, path, sig, sigcont, ignore_self, s);
273
274         if ((r = cg_enumerate_subgroups(controller, path, &d)) < 0) {
275                 if (ret >= 0 && r != -ENOENT)
276                         ret = r;
277
278                 goto finish;
279         }
280
281         while ((r = cg_read_subgroup(d, &fn)) > 0) {
282                 char *p = NULL;
283
284                 r = asprintf(&p, "%s/%s", path, fn);
285                 free(fn);
286
287                 if (r < 0) {
288                         if (ret >= 0)
289                                 ret = -ENOMEM;
290
291                         goto finish;
292                 }
293
294                 r = cg_kill_recursive(controller, p, sig, sigcont, ignore_self, rem, s);
295                 free(p);
296
297                 if (r != 0 && ret >= 0)
298                         ret = r;
299         }
300
301         if (r < 0 && ret >= 0)
302                 ret = r;
303
304         if (rem)
305                 if ((r = cg_rmdir(controller, path)) < 0) {
306                         if (ret >= 0 &&
307                             r != -ENOENT &&
308                             r != -EBUSY)
309                                 ret = r;
310                 }
311
312 finish:
313         if (d)
314                 closedir(d);
315
316         if (allocated_set)
317                 set_free(allocated_set);
318
319         return ret;
320 }
321
322 int cg_kill_recursive_and_wait(const char *controller, const char *path, bool rem) {
323         unsigned i;
324
325         assert(path);
326         assert(controller);
327
328         /* This safely kills all processes; first it sends a SIGTERM,
329          * then checks 8 times after 200ms whether the group is now
330          * empty, then kills everything that is left with SIGKILL and
331          * finally checks 5 times after 200ms each whether the group
332          * is finally empty. */
333
334         for (i = 0; i < 15; i++) {
335                 int sig, r;
336
337                 if (i <= 0)
338                         sig = SIGTERM;
339                 else if (i == 9)
340                         sig = SIGKILL;
341                 else
342                         sig = 0;
343
344                 if ((r = cg_kill_recursive(controller, path, sig, true, true, rem, NULL)) <= 0)
345                         return r;
346
347                 usleep(200 * USEC_PER_MSEC);
348         }
349
350         return 0;
351 }
352
353 int cg_migrate(const char *controller, const char *from, const char *to, bool ignore_self) {
354         bool done = false;
355         Set *s;
356         int r, ret = 0;
357         pid_t my_pid;
358         FILE *f = NULL;
359
360         assert(controller);
361         assert(from);
362         assert(to);
363
364         if (!(s = set_new(trivial_hash_func, trivial_compare_func)))
365                 return -ENOMEM;
366
367         my_pid = getpid();
368
369         do {
370                 pid_t pid = 0;
371                 done = true;
372
373                 if ((r = cg_enumerate_tasks(controller, from, &f)) < 0) {
374                         if (ret >= 0 && r != -ENOENT)
375                                 ret = r;
376
377                         goto finish;
378                 }
379
380                 while ((r = cg_read_pid(f, &pid)) > 0) {
381
382                         /* This might do weird stuff if we aren't a
383                          * single-threaded program. However, we
384                          * luckily know we are not */
385                         if (pid == my_pid && ignore_self)
386                                 continue;
387
388                         if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
389                                 continue;
390
391                         if ((r = cg_attach(controller, to, pid)) < 0) {
392                                 if (ret >= 0 && r != -ESRCH)
393                                         ret = r;
394                         } else if (ret == 0)
395                                 ret = 1;
396
397                         done = false;
398
399                         if ((r = set_put(s, LONG_TO_PTR(pid))) < 0) {
400                                 if (ret >= 0)
401                                         ret = r;
402
403                                 goto finish;
404                         }
405                 }
406
407                 if (r < 0) {
408                         if (ret >= 0)
409                                 ret = r;
410
411                         goto finish;
412                 }
413
414                 fclose(f);
415                 f = NULL;
416
417         } while (!done);
418
419 finish:
420         set_free(s);
421
422         if (f)
423                 fclose(f);
424
425         return ret;
426 }
427
428 int cg_migrate_recursive(const char *controller, const char *from, const char *to, bool ignore_self, bool rem) {
429         int r, ret = 0;
430         DIR *d = NULL;
431         char *fn;
432
433         assert(controller);
434         assert(from);
435         assert(to);
436
437         ret = cg_migrate(controller, from, to, ignore_self);
438
439         if ((r = cg_enumerate_subgroups(controller, from, &d)) < 0) {
440                 if (ret >= 0 && r != -ENOENT)
441                         ret = r;
442                 goto finish;
443         }
444
445         while ((r = cg_read_subgroup(d, &fn)) > 0) {
446                 char *p = NULL;
447
448                 r = asprintf(&p, "%s/%s", from, fn);
449                 free(fn);
450
451                 if (r < 0) {
452                         if (ret >= 0)
453                                 ret = -ENOMEM;
454
455                         goto finish;
456                 }
457
458                 r = cg_migrate_recursive(controller, p, to, ignore_self, rem);
459                 free(p);
460
461                 if (r != 0 && ret >= 0)
462                         ret = r;
463         }
464
465         if (r < 0 && ret >= 0)
466                 ret = r;
467
468         if (rem)
469                 if ((r = cg_rmdir(controller, from)) < 0) {
470                         if (ret >= 0 &&
471                             r != -ENOENT &&
472                             r != -EBUSY)
473                                 ret = r;
474                 }
475
476 finish:
477         if (d)
478                 closedir(d);
479
480         return ret;
481 }
482
483 int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) {
484         const char *p;
485         char *mp;
486         int r;
487
488         assert(controller);
489         assert(fs);
490
491         /* This is a very minimal lookup from controller names to
492          * paths. Since we have mounted most hierarchies ourselves
493          * should be kinda safe, but eventually we might want to
494          * extend this to have a fallback to actually check
495          * /proc/mounts. Might need caching then. */
496
497         if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
498                 p = "systemd";
499         else if (startswith(controller, "name="))
500                 p = controller + 5;
501         else
502                 p = controller;
503
504         if (asprintf(&mp, "/sys/fs/cgroup/%s", p) < 0)
505                 return -ENOMEM;
506
507         if ((r = path_is_mount_point(mp)) <= 0) {
508                 free(mp);
509                 return r < 0 ? r : -ENOENT;
510         }
511
512         if (path && suffix)
513                 r = asprintf(fs, "%s/%s/%s", mp, path, suffix);
514         else if (path)
515                 r = asprintf(fs, "%s/%s", mp, path);
516         else if (suffix)
517                 r = asprintf(fs, "%s/%s", mp, suffix);
518         else {
519                 path_kill_slashes(mp);
520                 *fs = mp;
521                 return 0;
522         }
523
524         free(mp);
525         path_kill_slashes(*fs);
526         return r < 0 ? -ENOMEM : 0;
527 }
528
529 int cg_trim(const char *controller, const char *path, bool delete_root) {
530         char *fs;
531         int r;
532
533         assert(controller);
534         assert(path);
535
536         if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
537                 return r;
538
539         r = rm_rf(fs, true, delete_root);
540         free(fs);
541
542         return r == -ENOENT ? 0 : r;
543 }
544
545 int cg_delete(const char *controller, const char *path) {
546         char *parent;
547         int r;
548
549         assert(controller);
550         assert(path);
551
552         if ((r = parent_of_path(path, &parent)) < 0)
553                 return r;
554
555         r = cg_migrate_recursive(controller, path, parent, false, true);
556         free(parent);
557
558         return r == -ENOENT ? 0 : r;
559 }
560
561 int cg_create(const char *controller, const char *path) {
562         char *fs;
563         int r;
564
565         assert(controller);
566         assert(path);
567
568         if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
569                 return r;
570
571         r = mkdir_parents(fs, 0755);
572
573         if (r >= 0) {
574                 if (mkdir(fs, 0755) >= 0)
575                         r = 1;
576                 else if (errno == EEXIST)
577                         r = 0;
578                 else
579                         r = -errno;
580         }
581
582         free(fs);
583
584         return r;
585 }
586
587 int cg_attach(const char *controller, const char *path, pid_t pid) {
588         char *fs;
589         int r;
590         char c[32];
591
592         assert(controller);
593         assert(path);
594         assert(pid >= 0);
595
596         if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
597                 return r;
598
599         if (pid == 0)
600                 pid = getpid();
601
602         snprintf(c, sizeof(c), "%lu\n", (unsigned long) pid);
603         char_array_0(c);
604
605         r = write_one_line_file(fs, c);
606         free(fs);
607
608         return r;
609 }
610
611 int cg_create_and_attach(const char *controller, const char *path, pid_t pid) {
612         int r, q;
613
614         assert(controller);
615         assert(path);
616         assert(pid >= 0);
617
618         if ((r = cg_create(controller, path)) < 0)
619                 return r;
620
621         if ((q = cg_attach(controller, path, pid)) < 0)
622                 return q;
623
624         /* This does not remove the cgroup on failure */
625
626         return r;
627 }
628
629 int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) {
630         char *fs;
631         int r;
632
633         assert(controller);
634         assert(path);
635
636         if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
637                 return r;
638
639         r = chmod_and_chown(fs, mode, uid, gid);
640         free(fs);
641
642         return r;
643 }
644
645 int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) {
646         char *fs;
647         int r;
648
649         assert(controller);
650         assert(path);
651
652         if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
653                 return r;
654
655         r = chmod_and_chown(fs, mode, uid, gid);
656         free(fs);
657
658         return r;
659 }
660
661 int cg_get_by_pid(const char *controller, pid_t pid, char **path) {
662         int r;
663         char *p = NULL;
664         FILE *f;
665         char *fs;
666         size_t cs;
667
668         assert(controller);
669         assert(path);
670         assert(pid >= 0);
671
672         if (pid == 0)
673                 pid = getpid();
674
675         if (asprintf(&fs, "/proc/%lu/cgroup", (unsigned long) pid) < 0)
676                 return -ENOMEM;
677
678         f = fopen(fs, "re");
679         free(fs);
680
681         if (!f)
682                 return errno == ENOENT ? -ESRCH : -errno;
683
684         cs = strlen(controller);
685
686         while (!feof(f)) {
687                 char line[LINE_MAX];
688                 char *l;
689
690                 errno = 0;
691                 if (!(fgets(line, sizeof(line), f))) {
692                         if (feof(f))
693                                 break;
694
695                         r = errno ? -errno : -EIO;
696                         goto finish;
697                 }
698
699                 truncate_nl(line);
700
701                 if (!(l = strchr(line, ':')))
702                         continue;
703
704                 l++;
705                 if (strncmp(l, controller, cs) != 0)
706                         continue;
707
708                 if (l[cs] != ':')
709                         continue;
710
711                 if (!(p = strdup(l + cs + 1))) {
712                         r = -ENOMEM;
713                         goto finish;
714                 }
715
716                 *path = p;
717                 r = 0;
718                 goto finish;
719         }
720
721         r = -ENOENT;
722
723 finish:
724         fclose(f);
725
726         return r;
727 }
728
729 int cg_install_release_agent(const char *controller, const char *agent) {
730         char *fs = NULL, *contents = NULL, *line = NULL, *sc;
731         int r;
732
733         assert(controller);
734         assert(agent);
735
736         if ((r = cg_get_path(controller, NULL, "release_agent", &fs)) < 0)
737                 return r;
738
739         if ((r = read_one_line_file(fs, &contents)) < 0)
740                 goto finish;
741
742         sc = strstrip(contents);
743         if (sc[0] == 0) {
744
745                 if (asprintf(&line, "%s\n", agent) < 0) {
746                         r = -ENOMEM;
747                         goto finish;
748                 }
749
750                 if ((r = write_one_line_file(fs, line)) < 0)
751                         goto finish;
752
753         } else if (!streq(sc, agent)) {
754                 r = -EEXIST;
755                 goto finish;
756         }
757
758         free(fs);
759         fs = NULL;
760         if ((r = cg_get_path(controller, NULL, "notify_on_release", &fs)) < 0)
761                 goto finish;
762
763         free(contents);
764         contents = NULL;
765         if ((r = read_one_line_file(fs, &contents)) < 0)
766                 goto finish;
767
768         sc = strstrip(contents);
769
770         if (streq(sc, "0")) {
771                 if ((r = write_one_line_file(fs, "1\n")) < 0)
772                         goto finish;
773
774                 r = 1;
775         } else if (!streq(sc, "1")) {
776                 r = -EIO;
777                 goto finish;
778         } else
779                 r = 0;
780
781 finish:
782         free(fs);
783         free(contents);
784         free(line);
785
786         return r;
787 }
788
789 int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
790         pid_t pid = 0;
791         int r;
792         FILE *f = NULL;
793         bool found = false;
794
795         assert(controller);
796         assert(path);
797
798         if ((r = cg_enumerate_tasks(controller, path, &f)) < 0)
799                 return r == -ENOENT ? 1 : r;
800
801         while ((r = cg_read_pid(f, &pid)) > 0) {
802
803                 if (ignore_self && pid == getpid())
804                         continue;
805
806                 found = true;
807                 break;
808         }
809
810         fclose(f);
811
812         if (r < 0)
813                 return r;
814
815         return !found;
816 }
817
818 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
819         int r;
820         DIR *d = NULL;
821         char *fn;
822
823         assert(controller);
824         assert(path);
825
826         if ((r = cg_is_empty(controller, path, ignore_self)) <= 0)
827                 return r;
828
829         if ((r = cg_enumerate_subgroups(controller, path, &d)) < 0)
830                 return r == -ENOENT ? 1 : r;
831
832         while ((r = cg_read_subgroup(d, &fn)) > 0) {
833                 char *p = NULL;
834
835                 r = asprintf(&p, "%s/%s", path, fn);
836                 free(fn);
837
838                 if (r < 0) {
839                         r = -ENOMEM;
840                         goto finish;
841                 }
842
843                 r = cg_is_empty_recursive(controller, p, ignore_self);
844                 free(p);
845
846                 if (r <= 0)
847                         goto finish;
848         }
849
850         if (r >= 0)
851                 r = 1;
852
853 finish:
854
855         if (d)
856                 closedir(d);
857
858         return r;
859 }
860
861 int cg_split_spec(const char *spec, char **controller, char **path) {
862         const char *e;
863         char *t = NULL, *u = NULL;
864
865         assert(spec);
866         assert(controller || path);
867
868         if (*spec == '/') {
869
870                 if (path) {
871                         if (!(t = strdup(spec)))
872                                 return -ENOMEM;
873
874                         *path = t;
875                 }
876
877                 if (controller)
878                         *controller = NULL;
879
880                 return 0;
881         }
882
883         if (!(e = strchr(spec, ':'))) {
884
885                 if (strchr(spec, '/') || spec[0] == 0)
886                         return -EINVAL;
887
888                 if (controller) {
889                         if (!(t = strdup(spec)))
890                                 return -ENOMEM;
891
892                         *controller = t;
893                 }
894
895                 if (path)
896                         *path = NULL;
897
898                 return 0;
899         }
900
901         if (e[1] != '/' ||
902             e == spec ||
903             memchr(spec, '/', e-spec))
904                 return -EINVAL;
905
906         if (controller)
907                 if (!(t = strndup(spec, e-spec)))
908                         return -ENOMEM;
909
910         if (path)
911                 if (!(u = strdup(e+1))) {
912                         free(t);
913                         return -ENOMEM;
914                 }
915
916         if (controller)
917                 *controller = t;
918
919         if (path)
920                 *path = u;
921
922         return 0;
923 }
924
925 int cg_join_spec(const char *controller, const char *path, char **spec) {
926         assert(controller);
927         assert(path);
928
929         if (!path_is_absolute(path) ||
930             controller[0] == 0 ||
931             strchr(controller, ':') ||
932             strchr(controller, '/'))
933                 return -EINVAL;
934
935         if (asprintf(spec, "%s:%s", controller, path) < 0)
936                 return -ENOMEM;
937
938         return 0;
939 }
940
941 int cg_fix_path(const char *path, char **result) {
942         char *t, *c, *p;
943         int r;
944
945         assert(path);
946         assert(result);
947
948         /* First check if it already is a filesystem path */
949         if (path_is_absolute(path) &&
950             path_startswith(path, "/sys/fs/cgroup") &&
951             access(path, F_OK) >= 0) {
952
953                 if (!(t = strdup(path)))
954                         return -ENOMEM;
955
956                 *result = t;
957                 return 0;
958         }
959
960         /* Otherwise treat it as cg spec */
961         if ((r = cg_split_spec(path, &c, &p)) < 0)
962                 return r;
963
964         r = cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
965         free(c);
966         free(p);
967
968         return r;
969 }