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