chiark / gitweb /
e38d6f5c1036b0f2dc8d34ed5c0cc555e1f938af
[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
28 #include <libcgroup.h>
29
30 #include "cgroup-util.h"
31 #include "log.h"
32 #include "set.h"
33 #include "macro.h"
34 #include "util.h"
35
36 /*
37    Currently, the only remaining functionality from libcgroup we call
38    here is:
39
40    - cgroup_walk_tree_begin()/cgroup_walk_tree_next()
41    - cgroup_delete_cgroup_ext()
42  */
43
44 int cg_translate_error(int error, int _errno) {
45
46         switch (error) {
47
48         case ECGROUPNOTCOMPILED:
49         case ECGROUPNOTMOUNTED:
50         case ECGROUPNOTEXIST:
51         case ECGROUPNOTCREATED:
52                 return -ENOENT;
53
54         case ECGINVAL:
55                 return -EINVAL;
56
57         case ECGROUPNOTALLOWED:
58                 return -EPERM;
59
60         case ECGOTHER:
61                 return -_errno;
62         }
63
64         return -EIO;
65 }
66
67 static struct cgroup* cg_new(const char *controller, const char *path) {
68         struct cgroup *cgroup;
69
70         assert(path);
71         assert(controller);
72
73         if (!(cgroup = cgroup_new_cgroup(path)))
74                 return NULL;
75
76         if (!cgroup_add_controller(cgroup, controller)) {
77                 cgroup_free(&cgroup);
78                 return NULL;
79         }
80
81         return cgroup;
82 }
83
84 int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
85         char *fs;
86         int r;
87         FILE *f;
88
89         assert(controller);
90         assert(path);
91         assert(_f);
92
93         if ((r = cg_get_path(controller, path, "cgroup.procs", &fs)) < 0)
94                 return r;
95
96         f = fopen(fs, "re");
97         free(fs);
98
99         if (!f)
100                 return -errno;
101
102         *_f = f;
103         return 0;
104 }
105
106 int cg_enumerate_tasks(const char *controller, const char *path, FILE **_f) {
107         char *fs;
108         int r;
109         FILE *f;
110
111         assert(controller);
112         assert(path);
113         assert(_f);
114
115         if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
116                 return r;
117
118         f = fopen(fs, "re");
119         free(fs);
120
121         if (!f)
122                 return -errno;
123
124         *_f = f;
125         return 0;
126 }
127
128 int cg_read_pid(FILE *f, pid_t *_pid) {
129         unsigned long ul;
130
131         /* Note that the cgroup.procs might contain duplicates! See
132          * cgroups.txt for details. */
133
134         errno = 0;
135         if (fscanf(f, "%lu", &ul) != 1) {
136
137                 if (feof(f))
138                         return 0;
139
140                 return errno ? -errno : -EIO;
141         }
142
143         if (ul <= 0)
144                 return -EIO;
145
146         *_pid = (pid_t) ul;
147         return 1;
148 }
149
150 int cg_kill(const char *controller, const char *path, int sig, bool ignore_self) {
151         bool killed = false, done = false;
152         Set *s;
153         pid_t my_pid;
154         int r, ret = 0;
155         FILE *f = NULL;
156
157         assert(controller);
158         assert(path);
159         assert(sig >= 0);
160
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 */
164
165         if (!(s = set_new(trivial_hash_func, trivial_compare_func)))
166                 return -ENOMEM;
167
168         my_pid = getpid();
169
170         do {
171                 pid_t pid;
172                 done = true;
173
174                 if ((r = cg_enumerate_processes(controller, path, &f)) < 0)
175                         goto finish;
176
177                 while ((r = cg_read_pid(f, &pid)) > 0) {
178
179                         if (pid == my_pid && ignore_self)
180                                 continue;
181
182                         if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
183                                 continue;
184
185                         /* If we haven't killed this process yet, kill
186                          * it */
187                         if (kill(pid, sig) < 0 && errno != ESRCH) {
188                                 if (ret == 0)
189                                         ret = -errno;
190                         }
191
192                         killed = true;
193                         done = false;
194
195                         if ((r = set_put(s, LONG_TO_PTR(pid))) < 0)
196                                 break;
197                 }
198
199                 fclose(f);
200                 f = NULL;
201
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. */
205
206         } while (!done && r >= 0);
207
208 finish:
209         set_free(s);
210
211         if (f)
212                 fclose(f);
213
214         if (r < 0)
215                 return r;
216
217         if (ret < 0)
218                 return ret;
219
220         return !!killed;
221 }
222
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;
227         bool killed = false;
228
229         assert(path);
230         assert(controller);
231         assert(sig >= 0);
232
233         zero(info);
234
235         r = cgroup_walk_tree_begin(controller, path, 0, &iterator, &info, &level);
236         while (r == 0) {
237                 int k;
238                 char *p;
239
240                 if (info.type != CGROUP_FILE_TYPE_DIR)
241                         goto next;
242
243                 if (asprintf(&p, "%s/%s", path, info.path) < 0) {
244                         ret = -ENOMEM;
245                         break;
246                 }
247
248                 k = cg_kill(controller, p, sig, ignore_self);
249                 free(p);
250
251                 if (k < 0) {
252                         if (ret == 0)
253                                 ret = k;
254                 } else if (k > 0)
255                         killed = true;
256
257         next:
258
259                 r = cgroup_walk_tree_next(0, &iterator, &info, level);
260         }
261
262         if (ret == 0) {
263                 if (r == 0 || r == ECGEOF)
264                         ret = !!killed;
265                 else if (r == ECGOTHER && errno == ENOENT)
266                         ret = -ESRCH;
267                 else
268                         ret = cg_translate_error(r, errno);
269         }
270
271         assert_se(cgroup_walk_tree_end(&iterator) == 0);
272
273         return ret;
274 }
275
276 int cg_kill_recursive_and_wait(const char *controller, const char *path) {
277         unsigned i;
278
279         assert(path);
280         assert(controller);
281
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
285          * SIGKILL */
286
287         for (i = 0; i < 10; i++) {
288                 int sig, r;
289
290                 if (i <= 0)
291                         sig = SIGTERM;
292                 else if (i >= 9)
293                         sig = SIGKILL;
294                 else
295                         sig = 0;
296
297                 if ((r = cg_kill_recursive(controller, path, sig, true)) <= 0)
298                         return r;
299
300                 usleep(50 * USEC_PER_MSEC);
301         }
302
303         return 0;
304 }
305
306 int cg_migrate(const char *controller, const char *from, const char *to, bool ignore_self) {
307         bool migrated = false, done = false;
308         int r, ret = 0;
309         pid_t my_pid;
310         FILE *f = NULL;
311
312         assert(controller);
313         assert(from);
314         assert(to);
315
316         my_pid = getpid();
317
318         do {
319                 pid_t pid;
320                 done = true;
321
322                 if ((r = cg_enumerate_tasks(controller, from, &f)) < 0)
323                         goto finish;
324
325                 while ((r = cg_read_pid(f, &pid)) > 0) {
326
327                         if (pid == my_pid && ignore_self)
328                                 continue;
329
330                         if ((r = cg_attach(controller, to, pid)) < 0) {
331                                 if (ret == 0)
332                                         ret = -r;
333                         }
334
335                         migrated = true;
336                         done = false;
337                 }
338
339                 fclose(f);
340                 f = NULL;
341
342         } while (!done && r >= 0);
343
344 finish:
345
346         if (f)
347                 fclose(f);
348
349         if (r < 0)
350                 return r;
351
352         if (ret < 0)
353                 return ret;
354
355         return !!migrated;
356 }
357
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;
363
364         assert(controller);
365         assert(from);
366         assert(to);
367
368         zero(info);
369
370         r = cgroup_walk_tree_begin(controller, from, 0, &iterator, &info, &level);
371         while (r == 0) {
372                 int k;
373                 char *p;
374
375                 if (info.type != CGROUP_FILE_TYPE_DIR)
376                         goto next;
377
378                 if (asprintf(&p, "%s/%s", from, info.path) < 0) {
379                         ret = -ENOMEM;
380                         break;
381                 }
382
383                 k = cg_migrate(controller, p, to, ignore_self);
384                 free(p);
385
386                 if (k < 0) {
387                         if (ret == 0)
388                                 ret = k;
389                 } else if (k > 0)
390                         migrated = true;
391
392         next:
393                 r = cgroup_walk_tree_next(0, &iterator, &info, level);
394         }
395
396         if (ret == 0) {
397                 if (r == 0 || r == ECGEOF)
398                         r = !!migrated;
399                 else if (r == ECGOTHER && errno == ENOENT)
400                         r = -ESRCH;
401                 else
402                         r = cg_translate_error(r, errno);
403         }
404
405         assert_se(cgroup_walk_tree_end(&iterator) == 0);
406
407         return ret;
408 }
409
410 int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) {
411         const char *p;
412         char *mp;
413         int r;
414
415         assert(controller);
416         assert(fs);
417
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. */
423
424         if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
425                 p = "systemd";
426         else if (startswith(controller, "name="))
427                 p = controller + 5;
428         else
429                 p = controller;
430
431         if (asprintf(&mp, "/cgroup/%s", p) < 0)
432                 return -ENOMEM;
433
434         if ((r = path_is_mount_point(mp)) <= 0) {
435                 free(mp);
436                 return r < 0 ? r : -ENOENT;
437         }
438
439         if (path && suffix)
440                 r = asprintf(fs, "%s/%s/%s", mp, path, suffix);
441         else if (path)
442                 r = asprintf(fs, "%s/%s", mp, path);
443         else if (suffix)
444                 r = asprintf(fs, "%s/%s", mp, suffix);
445         else {
446                 path_kill_slashes(mp);
447                 *fs = mp;
448                 return 0;
449         }
450
451         free(mp);
452         path_kill_slashes(*fs);
453         return r < 0 ? -ENOMEM : 0;
454 }
455
456 int cg_trim(const char *controller, const char *path, bool delete_root) {
457         char *fs;
458         int r;
459
460         assert(controller);
461         assert(path);
462
463         if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
464                 return r;
465
466         r = rm_rf(fs, true, delete_root);
467         free(fs);
468
469         return r;
470 }
471
472 int cg_delete(const char *controller, const char *path) {
473         struct cgroup *cg;
474         int r;
475
476         assert(controller);
477         assert(path);
478
479         if (!(cg = cg_new(controller, path)))
480                 return -ENOMEM;
481
482         if ((r = cgroup_delete_cgroup_ext(cg, CGFLAG_DELETE_RECURSIVE|CGFLAG_DELETE_IGNORE_MIGRATION)) != 0) {
483                 r = cg_translate_error(r, errno);
484                 goto finish;
485         }
486
487         r = 0;
488
489 finish:
490         cgroup_free(&cg);
491
492         return r;
493 }
494
495 int cg_create(const char *controller, const char *path) {
496         char *fs;
497         int r;
498
499         assert(controller);
500         assert(path);
501
502         if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
503                 return r;
504
505         r = mkdir_p(fs, 0755);
506         free(fs);
507
508         return r;
509 }
510
511 int cg_attach(const char *controller, const char *path, pid_t pid) {
512         char *fs;
513         int r;
514         char c[32];
515
516         assert(controller);
517         assert(path);
518         assert(pid >= 0);
519
520         if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
521                 return r;
522
523         if (pid == 0)
524                 pid = getpid();
525
526         snprintf(c, sizeof(c), "%lu\n", (unsigned long) pid);
527         char_array_0(c);
528
529         r = write_one_line_file(fs, c);
530         free(fs);
531
532         return r;
533 }
534
535 int cg_create_and_attach(const char *controller, const char *path, pid_t pid) {
536         int r;
537
538         assert(controller);
539         assert(path);
540         assert(pid >= 0);
541
542         if ((r = cg_create(controller, path)) < 0)
543                 return r;
544
545         if ((r = cg_attach(controller, path, pid)) < 0)
546                 return r;
547
548         /* This does not remove the cgroup on failure */
549
550         return r;
551 }
552
553 int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) {
554         char *fs;
555         int r;
556
557         assert(controller);
558         assert(path);
559
560         if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
561                 return r;
562
563         r = chmod_and_chown(fs, mode, uid, gid);
564         free(fs);
565
566         return r;
567 }
568
569 int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) {
570         char *fs;
571         int r;
572
573         assert(controller);
574         assert(path);
575
576         if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
577                 return r;
578
579         r = chmod_and_chown(fs, mode, uid, gid);
580         free(fs);
581
582         return r;
583 }
584
585 int cg_get_by_pid(const char *controller, pid_t pid, char **path) {
586         int r;
587         char *p = NULL;
588         FILE *f;
589         char *fs;
590         size_t cs;
591
592         assert(controller);
593         assert(path);
594         assert(pid >= 0);
595
596         if (pid == 0)
597                 pid = getpid();
598
599         if (asprintf(&fs, "/proc/%lu/cgroup", (unsigned long) pid) < 0)
600                 return -ENOMEM;
601
602         f = fopen(fs, "re");
603         free(fs);
604
605         cs = strlen(controller);
606
607         while (!feof(f)) {
608                 char line[LINE_MAX];
609                 char *l;
610
611                 errno = 0;
612                 if (!(fgets(line, sizeof(line), f))) {
613                         if (feof(f))
614                                 break;
615
616                         r = errno ? -errno : -EIO;
617                         goto finish;
618                 }
619
620                 truncate_nl(line);
621
622                 if (!(l = strchr(line, ':')))
623                         continue;
624
625                 l++;
626                 if (strncmp(l, controller, cs) != 0)
627                         continue;
628
629                 if (l[cs] != ':')
630                         continue;
631
632                 if (!(p = strdup(l + cs + 1))) {
633                         r = -ENOMEM;
634                         goto finish;
635                 }
636
637                 *path = p;
638                 r = 0;
639                 goto finish;
640         }
641
642         r = -ENOENT;
643
644 finish:
645         fclose(f);
646
647         return r;
648 }
649
650 int cg_install_release_agent(const char *controller, const char *agent) {
651         char *fs = NULL, *contents = NULL, *line = NULL, *sc;
652         int r;
653
654         assert(controller);
655         assert(agent);
656
657         if ((r = cg_get_path(controller, NULL, "release_agent", &fs)) < 0)
658                 return r;
659
660         if ((r = read_one_line_file(fs, &contents)) < 0)
661                 goto finish;
662
663         sc = strstrip(contents);
664         if (sc[0] == 0) {
665
666                 if (asprintf(&line, "%s\n", agent) < 0) {
667                         r = -ENOMEM;
668                         goto finish;
669                 }
670
671                 if ((r = write_one_line_file(fs, line)) < 0)
672                         goto finish;
673
674         } else if (!streq(sc, agent)) {
675                 r = -EEXIST;
676                 goto finish;
677         }
678
679         free(fs);
680         fs = NULL;
681         if ((r = cg_get_path(controller, NULL, "notify_on_release", &fs)) < 0) {
682                 r = -ENOMEM;
683                 goto finish;
684         }
685
686         free(contents);
687         contents = NULL;
688         if ((r = read_one_line_file(fs, &contents)) < 0)
689                 goto finish;
690
691         sc = strstrip(contents);
692
693         if (streq(sc, "0")) {
694                 if ((r = write_one_line_file(fs, "1\n")) < 0)
695                         goto finish;
696
697                 r = 1;
698         } else if (!streq(sc, "1")) {
699                 r = -EIO;
700                 goto finish;
701         } else
702                 r = 0;
703
704 finish:
705         free(fs);
706         free(contents);
707         free(line);
708
709         return r;
710 }
711
712 int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
713         pid_t pid;
714         int r;
715         FILE *f;
716         bool found = false;
717
718         assert(controller);
719         assert(path);
720
721         if ((r = cg_enumerate_tasks(controller, path, &f)) < 0)
722                 return r;
723
724         while ((r = cg_read_pid(f, &pid)) > 0) {
725
726                 if (ignore_self && pid == getpid())
727                         continue;
728
729                 found = true;
730                 break;
731         }
732
733         fclose(f);
734
735         if (r < 0)
736                 return r;
737
738         return !found;
739 }
740
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;
745         bool empty = true;
746
747         assert(controller);
748         assert(path);
749
750         zero(info);
751
752         r = cgroup_walk_tree_begin(controller, path, 0, &iterator, &info, &level);
753         while (r == 0) {
754                 int k;
755                 char *p;
756
757                 if (info.type != CGROUP_FILE_TYPE_DIR)
758                         goto next;
759
760                 if (asprintf(&p, "%s/%s", path, info.path) < 0) {
761                         ret = -ENOMEM;
762                         break;
763                 }
764
765                 k = cg_is_empty(controller, p, ignore_self);
766                 free(p);
767
768                 if (k < 0) {
769                         ret = k;
770                         break;
771                 } else if (k == 0) {
772                         empty = false;
773                         break;
774                 }
775
776         next:
777                 r = cgroup_walk_tree_next(0, &iterator, &info, level);
778         }
779
780         if (ret == 0) {
781                 if (r == 0 || r == ECGEOF)
782                         ret = !!empty;
783                 else if (r == ECGOTHER && errno == ENOENT)
784                         ret = -ESRCH;
785                 else
786                         ret = cg_translate_error(r, errno);
787         }
788
789         assert_se(cgroup_walk_tree_end(&iterator) == 0);
790
791         return ret;
792 }
793
794 int cg_init(void) {
795         int r;
796
797         if ((r = cgroup_init()) != 0)
798                 return cg_translate_error(r, errno);
799
800         return 0;
801 }