chiark / gitweb /
shutdown: don't try to shut down DM devices in a container
[elogind.git] / src / core / cgroup.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 Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 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   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <assert.h>
24 #include <unistd.h>
25 #include <sys/types.h>
26 #include <signal.h>
27 #include <sys/mount.h>
28 #include <fcntl.h>
29
30 #include "cgroup.h"
31 #include "cgroup-util.h"
32 #include "log.h"
33 #include "strv.h"
34
35 int cgroup_bonding_realize(CGroupBonding *b) {
36         int r;
37
38         assert(b);
39         assert(b->path);
40         assert(b->controller);
41
42         r = cg_create(b->controller, b->path);
43         if (r < 0) {
44                 log_warning("Failed to create cgroup %s:%s: %s", b->controller, b->path, strerror(-r));
45                 return r;
46         }
47
48         b->realized = true;
49
50         return 0;
51 }
52
53 int cgroup_bonding_realize_list(CGroupBonding *first) {
54         CGroupBonding *b;
55         int r;
56
57         LIST_FOREACH(by_unit, b, first)
58                 if ((r = cgroup_bonding_realize(b)) < 0 && b->essential)
59                         return r;
60
61         return 0;
62 }
63
64 void cgroup_bonding_free(CGroupBonding *b, bool trim) {
65         assert(b);
66
67         if (b->unit) {
68                 CGroupBonding *f;
69
70                 LIST_REMOVE(CGroupBonding, by_unit, b->unit->cgroup_bondings, b);
71
72                 if (streq(b->controller, SYSTEMD_CGROUP_CONTROLLER)) {
73                         assert_se(f = hashmap_get(b->unit->manager->cgroup_bondings, b->path));
74                         LIST_REMOVE(CGroupBonding, by_path, f, b);
75
76                         if (f)
77                                 hashmap_replace(b->unit->manager->cgroup_bondings, b->path, f);
78                         else
79                                 hashmap_remove(b->unit->manager->cgroup_bondings, b->path);
80                 }
81         }
82
83         if (b->realized && b->ours && trim)
84                 cg_trim(b->controller, b->path, false);
85
86         free(b->controller);
87         free(b->path);
88         free(b);
89 }
90
91 void cgroup_bonding_free_list(CGroupBonding *first, bool remove_or_trim) {
92         CGroupBonding *b, *n;
93
94         LIST_FOREACH_SAFE(by_unit, b, n, first)
95                 cgroup_bonding_free(b, remove_or_trim);
96 }
97
98 void cgroup_bonding_trim(CGroupBonding *b, bool delete_root) {
99         assert(b);
100
101         if (b->realized && b->ours)
102                 cg_trim(b->controller, b->path, delete_root);
103 }
104
105 void cgroup_bonding_trim_list(CGroupBonding *first, bool delete_root) {
106         CGroupBonding *b;
107
108         LIST_FOREACH(by_unit, b, first)
109                 cgroup_bonding_trim(b, delete_root);
110 }
111
112
113 int cgroup_bonding_install(CGroupBonding *b, pid_t pid, const char *cgroup_suffix) {
114         char *p = NULL;
115         const char *path;
116         int r;
117
118         assert(b);
119         assert(pid >= 0);
120
121         if (cgroup_suffix) {
122                 p = join(b->path, "/", cgroup_suffix, NULL);
123                 if (!p)
124                         return -ENOMEM;
125
126                 path = p;
127         } else
128                 path = b->path;
129
130         r = cg_create_and_attach(b->controller, path, pid);
131         free(p);
132
133         if (r < 0)
134                 return r;
135
136         b->realized = true;
137         return 0;
138 }
139
140 int cgroup_bonding_install_list(CGroupBonding *first, pid_t pid, const char *cgroup_suffix) {
141         CGroupBonding *b;
142         int r;
143
144         LIST_FOREACH(by_unit, b, first) {
145                 r = cgroup_bonding_install(b, pid, cgroup_suffix);
146                 if (r < 0 && b->essential)
147                         return r;
148         }
149
150         return 0;
151 }
152
153 int cgroup_bonding_set_group_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid) {
154         assert(b);
155
156         if (!b->realized)
157                 return -EINVAL;
158
159         return cg_set_group_access(b->controller, b->path, mode, uid, gid);
160 }
161
162 int cgroup_bonding_set_group_access_list(CGroupBonding *first, mode_t mode, uid_t uid, gid_t gid) {
163         CGroupBonding *b;
164         int r;
165
166         LIST_FOREACH(by_unit, b, first) {
167                 r = cgroup_bonding_set_group_access(b, mode, uid, gid);
168                 if (r < 0)
169                         return r;
170         }
171
172         return 0;
173 }
174
175 int cgroup_bonding_set_task_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid, int sticky) {
176         assert(b);
177
178         if (!b->realized)
179                 return -EINVAL;
180
181         return cg_set_task_access(b->controller, b->path, mode, uid, gid, sticky);
182 }
183
184 int cgroup_bonding_set_task_access_list(CGroupBonding *first, mode_t mode, uid_t uid, gid_t gid, int sticky) {
185         CGroupBonding *b;
186         int r;
187
188         LIST_FOREACH(by_unit, b, first) {
189                 r = cgroup_bonding_set_task_access(b, mode, uid, gid, sticky);
190                 if (r < 0)
191                         return r;
192         }
193
194         return 0;
195 }
196
197 int cgroup_bonding_kill(CGroupBonding *b, int sig, bool sigcont, Set *s, const char *cgroup_suffix) {
198         char *p = NULL;
199         const char *path;
200         int r;
201
202         assert(b);
203         assert(sig >= 0);
204
205         /* Don't kill cgroups that aren't ours */
206         if (!b->ours)
207                 return 0;
208
209         if (cgroup_suffix) {
210                 p = join(b->path, "/", cgroup_suffix, NULL);
211                 if (!p)
212                         return -ENOMEM;
213
214                 path = p;
215         } else
216                 path = b->path;
217
218         r = cg_kill_recursive(b->controller, path, sig, sigcont, true, false, s);
219         free(p);
220
221         return r;
222 }
223
224 int cgroup_bonding_kill_list(CGroupBonding *first, int sig, bool sigcont, Set *s, const char *cgroup_suffix) {
225         CGroupBonding *b;
226         Set *allocated_set = NULL;
227         int ret = -EAGAIN, r;
228
229         if (!first)
230                 return 0;
231
232         if (!s)
233                 if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func)))
234                         return -ENOMEM;
235
236         LIST_FOREACH(by_unit, b, first) {
237                 r = cgroup_bonding_kill(b, sig, sigcont, s, cgroup_suffix);
238                 if (r < 0) {
239                         if (r == -EAGAIN || r == -ESRCH)
240                                 continue;
241
242                         ret = r;
243                         goto finish;
244                 }
245
246                 if (ret < 0 || r > 0)
247                         ret = r;
248         }
249
250 finish:
251         if (allocated_set)
252                 set_free(allocated_set);
253
254         return ret;
255 }
256
257 /* Returns 1 if the group is empty, 0 if it is not, -EAGAIN if we
258  * cannot know */
259 int cgroup_bonding_is_empty(CGroupBonding *b) {
260         int r;
261
262         assert(b);
263
264         if ((r = cg_is_empty_recursive(b->controller, b->path, true)) < 0)
265                 return r;
266
267         /* If it is empty it is empty */
268         if (r > 0)
269                 return 1;
270
271         /* It's not only us using this cgroup, so we just don't know */
272         return b->ours ? 0 : -EAGAIN;
273 }
274
275 int cgroup_bonding_is_empty_list(CGroupBonding *first) {
276         CGroupBonding *b;
277
278         LIST_FOREACH(by_unit, b, first) {
279                 int r;
280
281                 if ((r = cgroup_bonding_is_empty(b)) < 0) {
282                         /* If this returned -EAGAIN, then we don't know if the
283                          * group is empty, so let's see if another group can
284                          * tell us */
285
286                         if (r != -EAGAIN)
287                                 return r;
288                 } else
289                         return r;
290         }
291
292         return -EAGAIN;
293 }
294
295 int manager_setup_cgroup(Manager *m) {
296         char *current = NULL, *path = NULL;
297         int r;
298         char suffix[32];
299
300         assert(m);
301
302         /* 0. Be nice to Ingo Molnar #628004 */
303         if (path_is_mount_point("/sys/fs/cgroup/systemd", false) <= 0) {
304                 log_warning("No control group support available, not creating root group.");
305                 return 0;
306         }
307
308         /* 1. Determine hierarchy */
309         r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 0, &current);
310         if (r < 0) {
311                 log_error("Cannot determine cgroup we are running in: %s", strerror(-r));
312                 goto finish;
313         }
314
315         if (m->running_as == MANAGER_SYSTEM)
316                 strcpy(suffix, "/system");
317         else {
318                 snprintf(suffix, sizeof(suffix), "/systemd-%lu", (unsigned long) getpid());
319                 char_array_0(suffix);
320         }
321
322         free(m->cgroup_hierarchy);
323         if (endswith(current, suffix)) {
324                 /* We probably got reexecuted and can continue to use our root cgroup */
325                 m->cgroup_hierarchy = current;
326                 current = NULL;
327
328         } else {
329                 /* We need a new root cgroup */
330                 m->cgroup_hierarchy = NULL;
331                 if (asprintf(&m->cgroup_hierarchy, "%s%s", streq(current, "/") ? "" : current, suffix) < 0) {
332                         log_error("Out of memory");
333                         r = -ENOMEM;
334                         goto finish;
335                 }
336         }
337
338         /* 2. Show data */
339         r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, NULL, &path);
340         if (r < 0) {
341                 log_error("Cannot find cgroup mount point: %s", strerror(-r));
342                 goto finish;
343         }
344
345         log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER ". File system hierarchy is at %s.", path);
346
347         /* 3. Install agent */
348         r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, SYSTEMD_CGROUP_AGENT_PATH);
349         if (r < 0)
350                 log_warning("Failed to install release agent, ignoring: %s", strerror(-r));
351         else if (r > 0)
352                 log_debug("Installed release agent.");
353         else
354                 log_debug("Release agent already installed.");
355
356         /* 4. Realize the group */
357         r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, 0);
358         if (r < 0) {
359                 log_error("Failed to create root cgroup hierarchy: %s", strerror(-r));
360                 goto finish;
361         }
362
363         /* 5. And pin it, so that it cannot be unmounted */
364         if (m->pin_cgroupfs_fd >= 0)
365                 close_nointr_nofail(m->pin_cgroupfs_fd);
366
367         m->pin_cgroupfs_fd = open(path, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK);
368         if (r < 0) {
369                 log_error("Failed to open pin file: %m");
370                 r = -errno;
371                 goto finish;
372         }
373
374         log_debug("Created root group.");
375
376         cg_shorten_controllers(m->default_controllers);
377
378 finish:
379         free(current);
380         free(path);
381
382         return r;
383 }
384
385 void manager_shutdown_cgroup(Manager *m, bool delete) {
386         assert(m);
387
388         if (delete && m->cgroup_hierarchy)
389                 cg_delete(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy);
390
391         if (m->pin_cgroupfs_fd >= 0) {
392                 close_nointr_nofail(m->pin_cgroupfs_fd);
393                 m->pin_cgroupfs_fd = -1;
394         }
395
396         free(m->cgroup_hierarchy);
397         m->cgroup_hierarchy = NULL;
398 }
399
400 int cgroup_bonding_get(Manager *m, const char *cgroup, CGroupBonding **bonding) {
401         CGroupBonding *b;
402         char *p;
403
404         assert(m);
405         assert(cgroup);
406         assert(bonding);
407
408         b = hashmap_get(m->cgroup_bondings, cgroup);
409         if (b) {
410                 *bonding = b;
411                 return 1;
412         }
413
414         p = strdup(cgroup);
415         if (!p)
416                 return -ENOMEM;
417
418         for (;;) {
419                 char *e;
420
421                 e = strrchr(p, '/');
422                 if (!e || e == p) {
423                         free(p);
424                         *bonding = NULL;
425                         return 0;
426                 }
427
428                 *e = 0;
429
430                 b = hashmap_get(m->cgroup_bondings, p);
431                 if (b) {
432                         free(p);
433                         *bonding = b;
434                         return 1;
435                 }
436         }
437 }
438
439 int cgroup_notify_empty(Manager *m, const char *group) {
440         CGroupBonding *l, *b;
441         int r;
442
443         assert(m);
444         assert(group);
445
446         r = cgroup_bonding_get(m, group, &l);
447         if (r <= 0)
448                 return r;
449
450         LIST_FOREACH(by_path, b, l) {
451                 int t;
452
453                 if (!b->unit)
454                         continue;
455
456                 t = cgroup_bonding_is_empty_list(b);
457                 if (t < 0) {
458
459                         /* If we don't know, we don't know */
460                         if (t != -EAGAIN)
461                                 log_warning("Failed to check whether cgroup is empty: %s", strerror(errno));
462
463                         continue;
464                 }
465
466                 if (t > 0) {
467                         /* If it is empty, let's delete it */
468                         cgroup_bonding_trim_list(b->unit->cgroup_bondings, true);
469
470                         if (UNIT_VTABLE(b->unit)->cgroup_notify_empty)
471                                 UNIT_VTABLE(b->unit)->cgroup_notify_empty(b->unit);
472                 }
473         }
474
475         return 0;
476 }
477
478 Unit* cgroup_unit_by_pid(Manager *m, pid_t pid) {
479         CGroupBonding *l, *b;
480         char *group = NULL;
481
482         assert(m);
483
484         if (pid <= 1)
485                 return NULL;
486
487         if (cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &group) < 0)
488                 return NULL;
489
490         l = hashmap_get(m->cgroup_bondings, group);
491
492         if (!l) {
493                 char *slash;
494
495                 while ((slash = strrchr(group, '/'))) {
496                         if (slash == group)
497                                 break;
498
499                         *slash = 0;
500
501                         if ((l = hashmap_get(m->cgroup_bondings, group)))
502                                 break;
503                 }
504         }
505
506         free(group);
507
508         LIST_FOREACH(by_path, b, l) {
509
510                 if (!b->unit)
511                         continue;
512
513                 if (b->ours)
514                         return b->unit;
515         }
516
517         return NULL;
518 }
519
520 CGroupBonding *cgroup_bonding_find_list(CGroupBonding *first, const char *controller) {
521         CGroupBonding *b;
522
523         assert(controller);
524
525         LIST_FOREACH(by_unit, b, first)
526                 if (streq(b->controller, controller))
527                         return b;
528
529         return NULL;
530 }
531
532 char *cgroup_bonding_to_string(CGroupBonding *b) {
533         char *r;
534
535         assert(b);
536
537         if (asprintf(&r, "%s:%s", b->controller, b->path) < 0)
538                 return NULL;
539
540         return r;
541 }
542
543 pid_t cgroup_bonding_search_main_pid(CGroupBonding *b) {
544         FILE *f;
545         pid_t pid = 0, npid, mypid;
546
547         assert(b);
548
549         if (!b->ours)
550                 return 0;
551
552         if (cg_enumerate_processes(b->controller, b->path, &f) < 0)
553                 return 0;
554
555         mypid = getpid();
556
557         while (cg_read_pid(f, &npid) > 0)  {
558                 pid_t ppid;
559
560                 if (npid == pid)
561                         continue;
562
563                 /* Ignore processes that aren't our kids */
564                 if (get_parent_of_pid(npid, &ppid) >= 0 && ppid != mypid)
565                         continue;
566
567                 if (pid != 0) {
568                         /* Dang, there's more than one daemonized PID
569                         in this group, so we don't know what process
570                         is the main process. */
571                         pid = 0;
572                         break;
573                 }
574
575                 pid = npid;
576         }
577
578         fclose(f);
579
580         return pid;
581 }
582
583 pid_t cgroup_bonding_search_main_pid_list(CGroupBonding *first) {
584         CGroupBonding *b;
585         pid_t pid;
586
587         /* Try to find a main pid from this cgroup, but checking if
588          * there's only one PID in the cgroup and returning it. Later
589          * on we might want to add additional, smarter heuristics
590          * here. */
591
592         LIST_FOREACH(by_unit, b, first)
593                 if ((pid = cgroup_bonding_search_main_pid(b)) != 0)
594                         return pid;
595
596         return 0;
597
598 }