chiark / gitweb /
Prep v228: Condense elogind source masks (3/5)
[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 2013 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 <fcntl.h>
23 #include <fnmatch.h>
24
25 #include "alloc-util.h"
26 #include "cgroup-util.h"
27 #include "cgroup.h"
28 #include "fd-util.h"
29 #include "fileio.h"
30 #include "fs-util.h"
31 #include "parse-util.h"
32 #include "path-util.h"
33 #include "process-util.h"
34 //#include "special.h"
35 #include "string-table.h"
36 #include "string-util.h"
37
38 #define CGROUP_CPU_QUOTA_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC)
39
40 #if 0 /// UNNEEDED by elogind
41 void cgroup_context_init(CGroupContext *c) {
42         assert(c);
43
44         /* Initialize everything to the kernel defaults, assuming the
45          * structure is preinitialized to 0 */
46
47         c->cpu_shares = CGROUP_CPU_SHARES_INVALID;
48         c->startup_cpu_shares = CGROUP_CPU_SHARES_INVALID;
49         c->cpu_quota_per_sec_usec = USEC_INFINITY;
50
51         c->memory_limit = (uint64_t) -1;
52
53         c->blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID;
54         c->startup_blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID;
55
56         c->tasks_max = (uint64_t) -1;
57
58         c->netclass_type = CGROUP_NETCLASS_TYPE_NONE;
59 }
60
61 void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a) {
62         assert(c);
63         assert(a);
64
65         LIST_REMOVE(device_allow, c->device_allow, a);
66         free(a->path);
67         free(a);
68 }
69
70 void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w) {
71         assert(c);
72         assert(w);
73
74         LIST_REMOVE(device_weights, c->blockio_device_weights, w);
75         free(w->path);
76         free(w);
77 }
78
79 void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b) {
80         assert(c);
81         assert(b);
82
83         LIST_REMOVE(device_bandwidths, c->blockio_device_bandwidths, b);
84         free(b->path);
85         free(b);
86 }
87
88 void cgroup_context_done(CGroupContext *c) {
89         assert(c);
90
91         while (c->blockio_device_weights)
92                 cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
93
94         while (c->blockio_device_bandwidths)
95                 cgroup_context_free_blockio_device_bandwidth(c, c->blockio_device_bandwidths);
96
97         while (c->device_allow)
98                 cgroup_context_free_device_allow(c, c->device_allow);
99 }
100
101 void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
102         CGroupBlockIODeviceBandwidth *b;
103         CGroupBlockIODeviceWeight *w;
104         CGroupDeviceAllow *a;
105         char u[FORMAT_TIMESPAN_MAX];
106
107         assert(c);
108         assert(f);
109
110         prefix = strempty(prefix);
111
112         fprintf(f,
113                 "%sCPUAccounting=%s\n"
114                 "%sBlockIOAccounting=%s\n"
115                 "%sMemoryAccounting=%s\n"
116                 "%sTasksAccounting=%s\n"
117                 "%sCPUShares=%" PRIu64 "\n"
118                 "%sStartupCPUShares=%" PRIu64 "\n"
119                 "%sCPUQuotaPerSecSec=%s\n"
120                 "%sBlockIOWeight=%" PRIu64 "\n"
121                 "%sStartupBlockIOWeight=%" PRIu64 "\n"
122                 "%sMemoryLimit=%" PRIu64 "\n"
123                 "%sTasksMax=%" PRIu64 "\n"
124                 "%sDevicePolicy=%s\n"
125                 "%sDelegate=%s\n",
126                 prefix, yes_no(c->cpu_accounting),
127                 prefix, yes_no(c->blockio_accounting),
128                 prefix, yes_no(c->memory_accounting),
129                 prefix, yes_no(c->tasks_accounting),
130                 prefix, c->cpu_shares,
131                 prefix, c->startup_cpu_shares,
132                 prefix, format_timespan(u, sizeof(u), c->cpu_quota_per_sec_usec, 1),
133                 prefix, c->blockio_weight,
134                 prefix, c->startup_blockio_weight,
135                 prefix, c->memory_limit,
136                 prefix, c->tasks_max,
137                 prefix, cgroup_device_policy_to_string(c->device_policy),
138                 prefix, yes_no(c->delegate));
139
140         LIST_FOREACH(device_allow, a, c->device_allow)
141                 fprintf(f,
142                         "%sDeviceAllow=%s %s%s%s\n",
143                         prefix,
144                         a->path,
145                         a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
146
147         LIST_FOREACH(device_weights, w, c->blockio_device_weights)
148                 fprintf(f,
149                         "%sBlockIODeviceWeight=%s %" PRIu64,
150                         prefix,
151                         w->path,
152                         w->weight);
153
154         LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
155                 char buf[FORMAT_BYTES_MAX];
156
157                 fprintf(f,
158                         "%s%s=%s %s\n",
159                         prefix,
160                         b->read ? "BlockIOReadBandwidth" : "BlockIOWriteBandwidth",
161                         b->path,
162                         format_bytes(buf, sizeof(buf), b->bandwidth));
163         }
164 }
165
166 static int lookup_blkio_device(const char *p, dev_t *dev) {
167         struct stat st;
168         int r;
169
170         assert(p);
171         assert(dev);
172
173         r = stat(p, &st);
174         if (r < 0)
175                 return log_warning_errno(errno, "Couldn't stat device %s: %m", p);
176
177         if (S_ISBLK(st.st_mode))
178                 *dev = st.st_rdev;
179         else if (major(st.st_dev) != 0) {
180                 /* If this is not a device node then find the block
181                  * device this file is stored on */
182                 *dev = st.st_dev;
183
184                 /* If this is a partition, try to get the originating
185                  * block device */
186                 block_get_whole_disk(*dev, dev);
187         } else {
188                 log_warning("%s is not a block device and file system block device cannot be determined or is not local.", p);
189                 return -ENODEV;
190         }
191
192         return 0;
193 }
194
195 static int whitelist_device(const char *path, const char *node, const char *acc) {
196         char buf[2+DECIMAL_STR_MAX(dev_t)*2+2+4];
197         struct stat st;
198         int r;
199
200         assert(path);
201         assert(acc);
202
203         if (stat(node, &st) < 0) {
204                 log_warning("Couldn't stat device %s", node);
205                 return -errno;
206         }
207
208         if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
209                 log_warning("%s is not a device.", node);
210                 return -ENODEV;
211         }
212
213         sprintf(buf,
214                 "%c %u:%u %s",
215                 S_ISCHR(st.st_mode) ? 'c' : 'b',
216                 major(st.st_rdev), minor(st.st_rdev),
217                 acc);
218
219         r = cg_set_attribute("devices", path, "devices.allow", buf);
220         if (r < 0)
221                 log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
222                                "Failed to set devices.allow on %s: %m", path);
223
224         return r;
225 }
226
227 static int whitelist_major(const char *path, const char *name, char type, const char *acc) {
228         _cleanup_fclose_ FILE *f = NULL;
229         char line[LINE_MAX];
230         bool good = false;
231         int r;
232
233         assert(path);
234         assert(acc);
235         assert(type == 'b' || type == 'c');
236
237         f = fopen("/proc/devices", "re");
238         if (!f)
239                 return log_warning_errno(errno, "Cannot open /proc/devices to resolve %s (%c): %m", name, type);
240
241         FOREACH_LINE(line, f, goto fail) {
242                 char buf[2+DECIMAL_STR_MAX(unsigned)+3+4], *p, *w;
243                 unsigned maj;
244
245                 truncate_nl(line);
246
247                 if (type == 'c' && streq(line, "Character devices:")) {
248                         good = true;
249                         continue;
250                 }
251
252                 if (type == 'b' && streq(line, "Block devices:")) {
253                         good = true;
254                         continue;
255                 }
256
257                 if (isempty(line)) {
258                         good = false;
259                         continue;
260                 }
261
262                 if (!good)
263                         continue;
264
265                 p = strstrip(line);
266
267                 w = strpbrk(p, WHITESPACE);
268                 if (!w)
269                         continue;
270                 *w = 0;
271
272                 r = safe_atou(p, &maj);
273                 if (r < 0)
274                         continue;
275                 if (maj <= 0)
276                         continue;
277
278                 w++;
279                 w += strspn(w, WHITESPACE);
280
281                 if (fnmatch(name, w, 0) != 0)
282                         continue;
283
284                 sprintf(buf,
285                         "%c %u:* %s",
286                         type,
287                         maj,
288                         acc);
289
290                 r = cg_set_attribute("devices", path, "devices.allow", buf);
291                 if (r < 0)
292                         log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
293                                        "Failed to set devices.allow on %s: %m", path);
294         }
295
296         return 0;
297
298 fail:
299         log_warning_errno(errno, "Failed to read /proc/devices: %m");
300         return -errno;
301 }
302
303 void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, uint32_t netclass, ManagerState state) {
304         bool is_root;
305         int r;
306
307         assert(c);
308         assert(path);
309
310         if (mask == 0)
311                 return;
312
313         /* Some cgroup attributes are not supported on the root cgroup,
314          * hence silently ignore */
315         is_root = isempty(path) || path_equal(path, "/");
316         if (is_root)
317                 /* Make sure we don't try to display messages with an empty path. */
318                 path = "/";
319
320         /* We generally ignore errors caused by read-only mounted
321          * cgroup trees (assuming we are running in a container then),
322          * and missing cgroups, i.e. EROFS and ENOENT. */
323
324         if ((mask & CGROUP_MASK_CPU) && !is_root) {
325                 char buf[MAX(DECIMAL_STR_MAX(uint64_t), DECIMAL_STR_MAX(usec_t)) + 1];
326
327                 sprintf(buf, "%" PRIu64 "\n",
328                         IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID ? c->startup_cpu_shares :
329                         c->cpu_shares != CGROUP_CPU_SHARES_INVALID ? c->cpu_shares : CGROUP_CPU_SHARES_DEFAULT);
330                 r = cg_set_attribute("cpu", path, "cpu.shares", buf);
331                 if (r < 0)
332                         log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
333                                        "Failed to set cpu.shares on %s: %m", path);
334
335                 sprintf(buf, USEC_FMT "\n", CGROUP_CPU_QUOTA_PERIOD_USEC);
336                 r = cg_set_attribute("cpu", path, "cpu.cfs_period_us", buf);
337                 if (r < 0)
338                         log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
339                                        "Failed to set cpu.cfs_period_us on %s: %m", path);
340
341                 if (c->cpu_quota_per_sec_usec != USEC_INFINITY) {
342                         sprintf(buf, USEC_FMT "\n", c->cpu_quota_per_sec_usec * CGROUP_CPU_QUOTA_PERIOD_USEC / USEC_PER_SEC);
343                         r = cg_set_attribute("cpu", path, "cpu.cfs_quota_us", buf);
344                 } else
345                         r = cg_set_attribute("cpu", path, "cpu.cfs_quota_us", "-1");
346                 if (r < 0)
347                         log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
348                                        "Failed to set cpu.cfs_quota_us on %s: %m", path);
349         }
350
351         if (mask & CGROUP_MASK_BLKIO) {
352                 char buf[MAX(DECIMAL_STR_MAX(uint64_t)+1,
353                               DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1)];
354                 CGroupBlockIODeviceWeight *w;
355                 CGroupBlockIODeviceBandwidth *b;
356
357                 if (!is_root) {
358                         sprintf(buf, "%" PRIu64 "\n",
359                                 IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ? c->startup_blockio_weight :
360                                 c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ? c->blockio_weight : CGROUP_BLKIO_WEIGHT_DEFAULT);
361                         r = cg_set_attribute("blkio", path, "blkio.weight", buf);
362                         if (r < 0)
363                                 log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
364                                                "Failed to set blkio.weight on %s: %m", path);
365
366                         /* FIXME: no way to reset this list */
367                         LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
368                                 dev_t dev;
369
370                                 r = lookup_blkio_device(w->path, &dev);
371                                 if (r < 0)
372                                         continue;
373
374                                 sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), w->weight);
375                                 r = cg_set_attribute("blkio", path, "blkio.weight_device", buf);
376                                 if (r < 0)
377                                         log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
378                                                        "Failed to set blkio.weight_device on %s: %m", path);
379                         }
380                 }
381
382                 /* FIXME: no way to reset this list */
383                 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
384                         const char *a;
385                         dev_t dev;
386
387                         r = lookup_blkio_device(b->path, &dev);
388                         if (r < 0)
389                                 continue;
390
391                         a = b->read ? "blkio.throttle.read_bps_device" : "blkio.throttle.write_bps_device";
392
393                         sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), b->bandwidth);
394                         r = cg_set_attribute("blkio", path, a, buf);
395                         if (r < 0)
396                                 log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
397                                                "Failed to set %s on %s: %m", a, path);
398                 }
399         }
400
401         if ((mask & CGROUP_MASK_MEMORY) && !is_root) {
402                 if (c->memory_limit != (uint64_t) -1) {
403                         char buf[DECIMAL_STR_MAX(uint64_t) + 1];
404
405                         sprintf(buf, "%" PRIu64 "\n", c->memory_limit);
406
407                         if (cg_unified() <= 0)
408                                 r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf);
409                         else
410                                 r = cg_set_attribute("memory", path, "memory.max", buf);
411
412                 } else {
413                         if (cg_unified() <= 0)
414                                 r = cg_set_attribute("memory", path, "memory.limit_in_bytes", "-1");
415                         else
416                                 r = cg_set_attribute("memory", path, "memory.max", "max");
417                 }
418
419                 if (r < 0)
420                         log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
421                                        "Failed to set memory.limit_in_bytes/memory.max on %s: %m", path);
422         }
423
424         if ((mask & CGROUP_MASK_DEVICES) && !is_root) {
425                 CGroupDeviceAllow *a;
426
427                 /* Changing the devices list of a populated cgroup
428                  * might result in EINVAL, hence ignore EINVAL
429                  * here. */
430
431                 if (c->device_allow || c->device_policy != CGROUP_AUTO)
432                         r = cg_set_attribute("devices", path, "devices.deny", "a");
433                 else
434                         r = cg_set_attribute("devices", path, "devices.allow", "a");
435                 if (r < 0)
436                         log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
437                                        "Failed to reset devices.list on %s: %m", path);
438
439                 if (c->device_policy == CGROUP_CLOSED ||
440                     (c->device_policy == CGROUP_AUTO && c->device_allow)) {
441                         static const char auto_devices[] =
442                                 "/dev/null\0" "rwm\0"
443                                 "/dev/zero\0" "rwm\0"
444                                 "/dev/full\0" "rwm\0"
445                                 "/dev/random\0" "rwm\0"
446                                 "/dev/urandom\0" "rwm\0"
447                                 "/dev/tty\0" "rwm\0"
448                                 "/dev/pts/ptmx\0" "rw\0"; /* /dev/pts/ptmx may not be duplicated, but accessed */
449
450                         const char *x, *y;
451
452                         NULSTR_FOREACH_PAIR(x, y, auto_devices)
453                                 whitelist_device(path, x, y);
454
455                         whitelist_major(path, "pts", 'c', "rw");
456                         whitelist_major(path, "kdbus", 'c', "rw");
457                         whitelist_major(path, "kdbus/*", 'c', "rw");
458                 }
459
460                 LIST_FOREACH(device_allow, a, c->device_allow) {
461                         char acc[4];
462                         unsigned k = 0;
463
464                         if (a->r)
465                                 acc[k++] = 'r';
466                         if (a->w)
467                                 acc[k++] = 'w';
468                         if (a->m)
469                                 acc[k++] = 'm';
470
471                         if (k == 0)
472                                 continue;
473
474                         acc[k++] = 0;
475
476                         if (startswith(a->path, "/dev/"))
477                                 whitelist_device(path, a->path, acc);
478                         else if (startswith(a->path, "block-"))
479                                 whitelist_major(path, a->path + 6, 'b', acc);
480                         else if (startswith(a->path, "char-"))
481                                 whitelist_major(path, a->path + 5, 'c', acc);
482                         else
483                                 log_debug("Ignoring device %s while writing cgroup attribute.", a->path);
484                 }
485         }
486
487         if ((mask & CGROUP_MASK_PIDS) && !is_root) {
488
489                 if (c->tasks_max != (uint64_t) -1) {
490                         char buf[DECIMAL_STR_MAX(uint64_t) + 2];
491
492                         sprintf(buf, "%" PRIu64 "\n", c->tasks_max);
493                         r = cg_set_attribute("pids", path, "pids.max", buf);
494                 } else
495                         r = cg_set_attribute("pids", path, "pids.max", "max");
496
497                 if (r < 0)
498                         log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
499                                        "Failed to set pids.max on %s: %m", path);
500         }
501
502         if (mask & CGROUP_MASK_NET_CLS) {
503                 char buf[DECIMAL_STR_MAX(uint32_t)];
504
505                 sprintf(buf, "%" PRIu32, netclass);
506
507                 r = cg_set_attribute("net_cls", path, "net_cls.classid", buf);
508                 if (r < 0)
509                         log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
510                                        "Failed to set net_cls.classid on %s: %m", path);
511         }
512 }
513
514 CGroupMask cgroup_context_get_mask(CGroupContext *c) {
515         CGroupMask mask = 0;
516
517         /* Figure out which controllers we need */
518
519         if (c->cpu_accounting ||
520             c->cpu_shares != CGROUP_CPU_SHARES_INVALID ||
521             c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID ||
522             c->cpu_quota_per_sec_usec != USEC_INFINITY)
523                 mask |= CGROUP_MASK_CPUACCT | CGROUP_MASK_CPU;
524
525         if (c->blockio_accounting ||
526             c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ||
527             c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ||
528             c->blockio_device_weights ||
529             c->blockio_device_bandwidths)
530                 mask |= CGROUP_MASK_BLKIO;
531
532         if (c->memory_accounting ||
533             c->memory_limit != (uint64_t) -1)
534                 mask |= CGROUP_MASK_MEMORY;
535
536         if (c->device_allow ||
537             c->device_policy != CGROUP_AUTO)
538                 mask |= CGROUP_MASK_DEVICES;
539
540         if (c->tasks_accounting ||
541             c->tasks_max != (uint64_t) -1)
542                 mask |= CGROUP_MASK_PIDS;
543
544         if (c->netclass_type != CGROUP_NETCLASS_TYPE_NONE)
545                 mask |= CGROUP_MASK_NET_CLS;
546
547         return mask;
548 }
549
550 CGroupMask unit_get_own_mask(Unit *u) {
551         CGroupContext *c;
552
553         /* Returns the mask of controllers the unit needs for itself */
554
555         c = unit_get_cgroup_context(u);
556         if (!c)
557                 return 0;
558
559         /* If delegation is turned on, then turn on all cgroups,
560          * unless we are on the legacy hierarchy and the process we
561          * fork into it is known to drop privileges, and hence
562          * shouldn't get access to the controllers.
563          *
564          * Note that on the unified hierarchy it is safe to delegate
565          * controllers to unprivileged services. */
566
567         if (c->delegate) {
568                 ExecContext *e;
569
570                 e = unit_get_exec_context(u);
571                 if (!e ||
572                     exec_context_maintains_privileges(e) ||
573                     cg_unified() > 0)
574                         return _CGROUP_MASK_ALL;
575         }
576
577         return cgroup_context_get_mask(c);
578 }
579
580 CGroupMask unit_get_members_mask(Unit *u) {
581         assert(u);
582
583         /* Returns the mask of controllers all of the unit's children
584          * require, merged */
585
586         if (u->cgroup_members_mask_valid)
587                 return u->cgroup_members_mask;
588
589         u->cgroup_members_mask = 0;
590
591         if (u->type == UNIT_SLICE) {
592                 Unit *member;
593                 Iterator i;
594
595                 SET_FOREACH(member, u->dependencies[UNIT_BEFORE], i) {
596
597                         if (member == u)
598                                 continue;
599
600                         if (UNIT_DEREF(member->slice) != u)
601                                 continue;
602
603                         u->cgroup_members_mask |=
604                                 unit_get_own_mask(member) |
605                                 unit_get_members_mask(member);
606                 }
607         }
608
609         u->cgroup_members_mask_valid = true;
610         return u->cgroup_members_mask;
611 }
612
613 CGroupMask unit_get_siblings_mask(Unit *u) {
614         assert(u);
615
616         /* Returns the mask of controllers all of the unit's siblings
617          * require, i.e. the members mask of the unit's parent slice
618          * if there is one. */
619
620         if (UNIT_ISSET(u->slice))
621                 return unit_get_members_mask(UNIT_DEREF(u->slice));
622
623         return unit_get_own_mask(u) | unit_get_members_mask(u);
624 }
625
626 CGroupMask unit_get_subtree_mask(Unit *u) {
627
628         /* Returns the mask of this subtree, meaning of the group
629          * itself and its children. */
630
631         return unit_get_own_mask(u) | unit_get_members_mask(u);
632 }
633
634 CGroupMask unit_get_target_mask(Unit *u) {
635         CGroupMask mask;
636
637         /* This returns the cgroup mask of all controllers to enable
638          * for a specific cgroup, i.e. everything it needs itself,
639          * plus all that its children need, plus all that its siblings
640          * need. This is primarily useful on the legacy cgroup
641          * hierarchy, where we need to duplicate each cgroup in each
642          * hierarchy that shall be enabled for it. */
643
644         mask = unit_get_own_mask(u) | unit_get_members_mask(u) | unit_get_siblings_mask(u);
645         mask &= u->manager->cgroup_supported;
646
647         return mask;
648 }
649
650 CGroupMask unit_get_enable_mask(Unit *u) {
651         CGroupMask mask;
652
653         /* This returns the cgroup mask of all controllers to enable
654          * for the children of a specific cgroup. This is primarily
655          * useful for the unified cgroup hierarchy, where each cgroup
656          * controls which controllers are enabled for its children. */
657
658         mask = unit_get_members_mask(u);
659         mask &= u->manager->cgroup_supported;
660
661         return mask;
662 }
663
664 /* Recurse from a unit up through its containing slices, propagating
665  * mask bits upward. A unit is also member of itself. */
666 void unit_update_cgroup_members_masks(Unit *u) {
667         CGroupMask m;
668         bool more;
669
670         assert(u);
671
672         /* Calculate subtree mask */
673         m = unit_get_subtree_mask(u);
674
675         /* See if anything changed from the previous invocation. If
676          * not, we're done. */
677         if (u->cgroup_subtree_mask_valid && m == u->cgroup_subtree_mask)
678                 return;
679
680         more =
681                 u->cgroup_subtree_mask_valid &&
682                 ((m & ~u->cgroup_subtree_mask) != 0) &&
683                 ((~m & u->cgroup_subtree_mask) == 0);
684
685         u->cgroup_subtree_mask = m;
686         u->cgroup_subtree_mask_valid = true;
687
688         if (UNIT_ISSET(u->slice)) {
689                 Unit *s = UNIT_DEREF(u->slice);
690
691                 if (more)
692                         /* There's more set now than before. We
693                          * propagate the new mask to the parent's mask
694                          * (not caring if it actually was valid or
695                          * not). */
696
697                         s->cgroup_members_mask |= m;
698
699                 else
700                         /* There's less set now than before (or we
701                          * don't know), we need to recalculate
702                          * everything, so let's invalidate the
703                          * parent's members mask */
704
705                         s->cgroup_members_mask_valid = false;
706
707                 /* And now make sure that this change also hits our
708                  * grandparents */
709                 unit_update_cgroup_members_masks(s);
710         }
711 }
712
713 static const char *migrate_callback(CGroupMask mask, void *userdata) {
714         Unit *u = userdata;
715
716         assert(mask != 0);
717         assert(u);
718
719         while (u) {
720                 if (u->cgroup_path &&
721                     u->cgroup_realized &&
722                     (u->cgroup_realized_mask & mask) == mask)
723                         return u->cgroup_path;
724
725                 u = UNIT_DEREF(u->slice);
726         }
727
728         return NULL;
729 }
730
731 char *unit_default_cgroup_path(Unit *u) {
732         _cleanup_free_ char *escaped = NULL, *slice = NULL;
733         int r;
734
735         assert(u);
736
737         if (unit_has_name(u, SPECIAL_ROOT_SLICE))
738                 return strdup(u->manager->cgroup_root);
739
740         if (UNIT_ISSET(u->slice) && !unit_has_name(UNIT_DEREF(u->slice), SPECIAL_ROOT_SLICE)) {
741                 r = cg_slice_to_path(UNIT_DEREF(u->slice)->id, &slice);
742                 if (r < 0)
743                         return NULL;
744         }
745
746         escaped = cg_escape(u->id);
747         if (!escaped)
748                 return NULL;
749
750         if (slice)
751                 return strjoin(u->manager->cgroup_root, "/", slice, "/", escaped, NULL);
752         else
753                 return strjoin(u->manager->cgroup_root, "/", escaped, NULL);
754 }
755
756 int unit_set_cgroup_path(Unit *u, const char *path) {
757         _cleanup_free_ char *p = NULL;
758         int r;
759
760         assert(u);
761
762         if (path) {
763                 p = strdup(path);
764                 if (!p)
765                         return -ENOMEM;
766         } else
767                 p = NULL;
768
769         if (streq_ptr(u->cgroup_path, p))
770                 return 0;
771
772         if (p) {
773                 r = hashmap_put(u->manager->cgroup_unit, p, u);
774                 if (r < 0)
775                         return r;
776         }
777
778         unit_release_cgroup(u);
779
780         u->cgroup_path = p;
781         p = NULL;
782
783         return 1;
784 }
785
786 int unit_watch_cgroup(Unit *u) {
787         _cleanup_free_ char *populated = NULL;
788         int r;
789
790         assert(u);
791
792         if (!u->cgroup_path)
793                 return 0;
794
795         if (u->cgroup_inotify_wd >= 0)
796                 return 0;
797
798         /* Only applies to the unified hierarchy */
799         r = cg_unified();
800         if (r < 0)
801                 return log_unit_error_errno(u, r, "Failed detect wether the unified hierarchy is used: %m");
802         if (r == 0)
803                 return 0;
804
805         /* Don't watch the root slice, it's pointless. */
806         if (unit_has_name(u, SPECIAL_ROOT_SLICE))
807                 return 0;
808
809         r = hashmap_ensure_allocated(&u->manager->cgroup_inotify_wd_unit, &trivial_hash_ops);
810         if (r < 0)
811                 return log_oom();
812
813         r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "cgroup.populated", &populated);
814         if (r < 0)
815                 return log_oom();
816
817         u->cgroup_inotify_wd = inotify_add_watch(u->manager->cgroup_inotify_fd, populated, IN_MODIFY);
818         if (u->cgroup_inotify_wd < 0) {
819
820                 if (errno == ENOENT) /* If the directory is already
821                                       * gone we don't need to track
822                                       * it, so this is not an error */
823                         return 0;
824
825                 return log_unit_error_errno(u, errno, "Failed to add inotify watch descriptor for control group %s: %m", u->cgroup_path);
826         }
827
828         r = hashmap_put(u->manager->cgroup_inotify_wd_unit, INT_TO_PTR(u->cgroup_inotify_wd), u);
829         if (r < 0)
830                 return log_unit_error_errno(u, r, "Failed to add inotify watch descriptor to hash map: %m");
831
832         return 0;
833 }
834
835 static int unit_create_cgroup(
836                 Unit *u,
837                 CGroupMask target_mask,
838                 CGroupMask enable_mask) {
839
840         CGroupContext *c;
841         int r;
842
843         assert(u);
844
845         c = unit_get_cgroup_context(u);
846         if (!c)
847                 return 0;
848
849         if (!u->cgroup_path) {
850                 _cleanup_free_ char *path = NULL;
851
852                 path = unit_default_cgroup_path(u);
853                 if (!path)
854                         return log_oom();
855
856                 r = unit_set_cgroup_path(u, path);
857                 if (r == -EEXIST)
858                         return log_unit_error_errno(u, r, "Control group %s exists already.", path);
859                 if (r < 0)
860                         return log_unit_error_errno(u, r, "Failed to set unit's control group path to %s: %m", path);
861         }
862
863         /* First, create our own group */
864         r = cg_create_everywhere(u->manager->cgroup_supported, target_mask, u->cgroup_path);
865         if (r < 0)
866                 return log_unit_error_errno(u, r, "Failed to create cgroup %s: %m", u->cgroup_path);
867
868         /* Start watching it */
869         (void) unit_watch_cgroup(u);
870
871         /* Enable all controllers we need */
872         r = cg_enable_everywhere(u->manager->cgroup_supported, enable_mask, u->cgroup_path);
873         if (r < 0)
874                 log_unit_warning_errno(u, r, "Failed to enable controllers on cgroup %s, ignoring: %m", u->cgroup_path);
875
876         /* Keep track that this is now realized */
877         u->cgroup_realized = true;
878         u->cgroup_realized_mask = target_mask;
879
880         if (u->type != UNIT_SLICE && !c->delegate) {
881
882                 /* Then, possibly move things over, but not if
883                  * subgroups may contain processes, which is the case
884                  * for slice and delegation units. */
885                 r = cg_migrate_everywhere(u->manager->cgroup_supported, u->cgroup_path, u->cgroup_path, migrate_callback, u);
886                 if (r < 0)
887                         log_unit_warning_errno(u, r, "Failed to migrate cgroup from to %s, ignoring: %m", u->cgroup_path);
888         }
889
890         return 0;
891 }
892
893 int unit_attach_pids_to_cgroup(Unit *u) {
894         int r;
895         assert(u);
896
897         r = unit_realize_cgroup(u);
898         if (r < 0)
899                 return r;
900
901         r = cg_attach_many_everywhere(u->manager->cgroup_supported, u->cgroup_path, u->pids, migrate_callback, u);
902         if (r < 0)
903                 return r;
904
905         return 0;
906 }
907
908 static bool unit_has_mask_realized(Unit *u, CGroupMask target_mask) {
909         assert(u);
910
911         return u->cgroup_realized && u->cgroup_realized_mask == target_mask;
912 }
913
914 static int unit_find_free_netclass_cgroup(Unit *u, uint32_t *ret) {
915
916         uint32_t start, i;
917         Manager *m;
918
919         assert(u);
920
921         m = u->manager;
922
923         i = start = m->cgroup_netclass_registry_last;
924
925         do {
926                 i++;
927
928                 if (!hashmap_get(m->cgroup_netclass_registry, UINT_TO_PTR(i))) {
929                         m->cgroup_netclass_registry_last = i;
930                         *ret = i;
931                         return 0;
932                 }
933
934                 if (i == UINT32_MAX)
935                         i = CGROUP_NETCLASS_FIXED_MAX;
936
937         } while (i != start);
938
939         return -ENOBUFS;
940 }
941
942 int unit_add_to_netclass_cgroup(Unit *u) {
943
944         CGroupContext *cc;
945         Unit *first;
946         void *key;
947         int r;
948
949         assert(u);
950
951         cc = unit_get_cgroup_context(u);
952         if (!cc)
953                 return 0;
954
955         switch (cc->netclass_type) {
956         case CGROUP_NETCLASS_TYPE_NONE:
957                 return 0;
958
959         case CGROUP_NETCLASS_TYPE_FIXED:
960                 u->cgroup_netclass_id = cc->netclass_id;
961                 break;
962
963         case CGROUP_NETCLASS_TYPE_AUTO:
964                 /* Allocate a new ID in case it was requested and not done yet */
965                 if (u->cgroup_netclass_id == 0) {
966                         r = unit_find_free_netclass_cgroup(u, &u->cgroup_netclass_id);
967                         if (r < 0)
968                                 return r;
969
970                         log_debug("Dynamically assigned netclass cgroup id %" PRIu32 " to %s", u->cgroup_netclass_id, u->id);
971                 }
972
973                 break;
974         }
975
976         r = hashmap_ensure_allocated(&u->manager->cgroup_netclass_registry, &trivial_hash_ops);
977         if (r < 0)
978                 return r;
979
980         key = UINT32_TO_PTR(u->cgroup_netclass_id);
981         first = hashmap_get(u->manager->cgroup_netclass_registry, key);
982
983         if (first) {
984                 LIST_PREPEND(cgroup_netclass, first, u);
985                 return hashmap_replace(u->manager->cgroup_netclass_registry, key, u);
986         }
987
988         return hashmap_put(u->manager->cgroup_netclass_registry, key, u);
989 }
990
991 int unit_remove_from_netclass_cgroup(Unit *u) {
992
993         Unit *head;
994         void *key;
995
996         assert(u);
997
998         key = UINT32_TO_PTR(u->cgroup_netclass_id);
999
1000         LIST_FIND_HEAD(cgroup_netclass, u, head);
1001         LIST_REMOVE(cgroup_netclass, head, u);
1002
1003         if (head)
1004                 return hashmap_replace(u->manager->cgroup_netclass_registry, key, head);
1005
1006         hashmap_remove(u->manager->cgroup_netclass_registry, key);
1007
1008         return 0;
1009 }
1010
1011 /* Check if necessary controllers and attributes for a unit are in place.
1012  *
1013  * If so, do nothing.
1014  * If not, create paths, move processes over, and set attributes.
1015  *
1016  * Returns 0 on success and < 0 on failure. */
1017 static int unit_realize_cgroup_now(Unit *u, ManagerState state) {
1018         CGroupMask target_mask, enable_mask;
1019         int r;
1020
1021         assert(u);
1022
1023         if (u->in_cgroup_queue) {
1024                 LIST_REMOVE(cgroup_queue, u->manager->cgroup_queue, u);
1025                 u->in_cgroup_queue = false;
1026         }
1027
1028         target_mask = unit_get_target_mask(u);
1029         if (unit_has_mask_realized(u, target_mask))
1030                 return 0;
1031
1032         /* First, realize parents */
1033         if (UNIT_ISSET(u->slice)) {
1034                 r = unit_realize_cgroup_now(UNIT_DEREF(u->slice), state);
1035                 if (r < 0)
1036                         return r;
1037         }
1038
1039         /* And then do the real work */
1040         enable_mask = unit_get_enable_mask(u);
1041         r = unit_create_cgroup(u, target_mask, enable_mask);
1042         if (r < 0)
1043                 return r;
1044
1045         /* Finally, apply the necessary attributes. */
1046         cgroup_context_apply(unit_get_cgroup_context(u), target_mask, u->cgroup_path, u->cgroup_netclass_id, state);
1047
1048         return 0;
1049 }
1050
1051 static void unit_add_to_cgroup_queue(Unit *u) {
1052
1053         if (u->in_cgroup_queue)
1054                 return;
1055
1056         LIST_PREPEND(cgroup_queue, u->manager->cgroup_queue, u);
1057         u->in_cgroup_queue = true;
1058 }
1059
1060 unsigned manager_dispatch_cgroup_queue(Manager *m) {
1061         ManagerState state;
1062         unsigned n = 0;
1063         Unit *i;
1064         int r;
1065
1066         state = manager_state(m);
1067
1068         while ((i = m->cgroup_queue)) {
1069                 assert(i->in_cgroup_queue);
1070
1071                 r = unit_realize_cgroup_now(i, state);
1072                 if (r < 0)
1073                         log_warning_errno(r, "Failed to realize cgroups for queued unit %s, ignoring: %m", i->id);
1074
1075                 n++;
1076         }
1077
1078         return n;
1079 }
1080
1081 static void unit_queue_siblings(Unit *u) {
1082         Unit *slice;
1083
1084         /* This adds the siblings of the specified unit and the
1085          * siblings of all parent units to the cgroup queue. (But
1086          * neither the specified unit itself nor the parents.) */
1087
1088         while ((slice = UNIT_DEREF(u->slice))) {
1089                 Iterator i;
1090                 Unit *m;
1091
1092                 SET_FOREACH(m, slice->dependencies[UNIT_BEFORE], i) {
1093                         if (m == u)
1094                                 continue;
1095
1096                         /* Skip units that have a dependency on the slice
1097                          * but aren't actually in it. */
1098                         if (UNIT_DEREF(m->slice) != slice)
1099                                 continue;
1100
1101                         /* No point in doing cgroup application for units
1102                          * without active processes. */
1103                         if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(m)))
1104                                 continue;
1105
1106                         /* If the unit doesn't need any new controllers
1107                          * and has current ones realized, it doesn't need
1108                          * any changes. */
1109                         if (unit_has_mask_realized(m, unit_get_target_mask(m)))
1110                                 continue;
1111
1112                         unit_add_to_cgroup_queue(m);
1113                 }
1114
1115                 u = slice;
1116         }
1117 }
1118
1119 int unit_realize_cgroup(Unit *u) {
1120         assert(u);
1121
1122         if (!UNIT_HAS_CGROUP_CONTEXT(u))
1123                 return 0;
1124
1125         /* So, here's the deal: when realizing the cgroups for this
1126          * unit, we need to first create all parents, but there's more
1127          * actually: for the weight-based controllers we also need to
1128          * make sure that all our siblings (i.e. units that are in the
1129          * same slice as we are) have cgroups, too. Otherwise, things
1130          * would become very uneven as each of their processes would
1131          * get as much resources as all our group together. This call
1132          * will synchronously create the parent cgroups, but will
1133          * defer work on the siblings to the next event loop
1134          * iteration. */
1135
1136         /* Add all sibling slices to the cgroup queue. */
1137         unit_queue_siblings(u);
1138
1139         /* And realize this one now (and apply the values) */
1140         return unit_realize_cgroup_now(u, manager_state(u->manager));
1141 }
1142
1143 void unit_release_cgroup(Unit *u) {
1144         assert(u);
1145
1146         /* Forgets all cgroup details for this cgroup */
1147
1148         if (u->cgroup_path) {
1149                 (void) hashmap_remove(u->manager->cgroup_unit, u->cgroup_path);
1150                 u->cgroup_path = mfree(u->cgroup_path);
1151         }
1152
1153         if (u->cgroup_inotify_wd >= 0) {
1154                 if (inotify_rm_watch(u->manager->cgroup_inotify_fd, u->cgroup_inotify_wd) < 0)
1155                         log_unit_debug_errno(u, errno, "Failed to remove cgroup inotify watch %i for %s, ignoring", u->cgroup_inotify_wd, u->id);
1156
1157                 (void) hashmap_remove(u->manager->cgroup_inotify_wd_unit, INT_TO_PTR(u->cgroup_inotify_wd));
1158                 u->cgroup_inotify_wd = -1;
1159         }
1160 }
1161
1162 void unit_prune_cgroup(Unit *u) {
1163         int r;
1164         bool is_root_slice;
1165
1166         assert(u);
1167
1168         /* Removes the cgroup, if empty and possible, and stops watching it. */
1169
1170         if (!u->cgroup_path)
1171                 return;
1172
1173         is_root_slice = unit_has_name(u, SPECIAL_ROOT_SLICE);
1174
1175         r = cg_trim_everywhere(u->manager->cgroup_supported, u->cgroup_path, !is_root_slice);
1176         if (r < 0) {
1177                 log_debug_errno(r, "Failed to destroy cgroup %s, ignoring: %m", u->cgroup_path);
1178                 return;
1179         }
1180
1181         if (is_root_slice)
1182                 return;
1183
1184         unit_release_cgroup(u);
1185
1186         u->cgroup_realized = false;
1187         u->cgroup_realized_mask = 0;
1188 }
1189
1190 int unit_search_main_pid(Unit *u, pid_t *ret) {
1191         _cleanup_fclose_ FILE *f = NULL;
1192         pid_t pid = 0, npid, mypid;
1193         int r;
1194
1195         assert(u);
1196         assert(ret);
1197
1198         if (!u->cgroup_path)
1199                 return -ENXIO;
1200
1201         r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &f);
1202         if (r < 0)
1203                 return r;
1204
1205         mypid = getpid();
1206         while (cg_read_pid(f, &npid) > 0)  {
1207                 pid_t ppid;
1208
1209                 if (npid == pid)
1210                         continue;
1211
1212                 /* Ignore processes that aren't our kids */
1213                 if (get_process_ppid(npid, &ppid) >= 0 && ppid != mypid)
1214                         continue;
1215
1216                 if (pid != 0)
1217                         /* Dang, there's more than one daemonized PID
1218                         in this group, so we don't know what process
1219                         is the main process. */
1220
1221                         return -ENODATA;
1222
1223                 pid = npid;
1224         }
1225
1226         *ret = pid;
1227         return 0;
1228 }
1229
1230 static int unit_watch_pids_in_path(Unit *u, const char *path) {
1231         _cleanup_closedir_ DIR *d = NULL;
1232         _cleanup_fclose_ FILE *f = NULL;
1233         int ret = 0, r;
1234
1235         assert(u);
1236         assert(path);
1237
1238         r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, path, &f);
1239         if (r < 0)
1240                 ret = r;
1241         else {
1242                 pid_t pid;
1243
1244                 while ((r = cg_read_pid(f, &pid)) > 0) {
1245                         r = unit_watch_pid(u, pid);
1246                         if (r < 0 && ret >= 0)
1247                                 ret = r;
1248                 }
1249
1250                 if (r < 0 && ret >= 0)
1251                         ret = r;
1252         }
1253
1254         r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, path, &d);
1255         if (r < 0) {
1256                 if (ret >= 0)
1257                         ret = r;
1258         } else {
1259                 char *fn;
1260
1261                 while ((r = cg_read_subgroup(d, &fn)) > 0) {
1262                         _cleanup_free_ char *p = NULL;
1263
1264                         p = strjoin(path, "/", fn, NULL);
1265                         free(fn);
1266
1267                         if (!p)
1268                                 return -ENOMEM;
1269
1270                         r = unit_watch_pids_in_path(u, p);
1271                         if (r < 0 && ret >= 0)
1272                                 ret = r;
1273                 }
1274
1275                 if (r < 0 && ret >= 0)
1276                         ret = r;
1277         }
1278
1279         return ret;
1280 }
1281
1282 int unit_watch_all_pids(Unit *u) {
1283         assert(u);
1284
1285         /* Adds all PIDs from our cgroup to the set of PIDs we
1286          * watch. This is a fallback logic for cases where we do not
1287          * get reliable cgroup empty notifications: we try to use
1288          * SIGCHLD as replacement. */
1289
1290         if (!u->cgroup_path)
1291                 return -ENOENT;
1292
1293         if (cg_unified() > 0) /* On unified we can use proper notifications */
1294                 return 0;
1295
1296         return unit_watch_pids_in_path(u, u->cgroup_path);
1297 }
1298
1299 int unit_notify_cgroup_empty(Unit *u) {
1300         int r;
1301
1302         assert(u);
1303
1304         if (!u->cgroup_path)
1305                 return 0;
1306
1307         r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path);
1308         if (r <= 0)
1309                 return r;
1310
1311         unit_add_to_gc_queue(u);
1312
1313         if (UNIT_VTABLE(u)->notify_cgroup_empty)
1314                 UNIT_VTABLE(u)->notify_cgroup_empty(u);
1315
1316         return 0;
1317 }
1318
1319 static int on_cgroup_inotify_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
1320         Manager *m = userdata;
1321
1322         assert(s);
1323         assert(fd >= 0);
1324         assert(m);
1325
1326         for (;;) {
1327                 union inotify_event_buffer buffer;
1328                 struct inotify_event *e;
1329                 ssize_t l;
1330
1331                 l = read(fd, &buffer, sizeof(buffer));
1332                 if (l < 0) {
1333                         if (errno == EINTR || errno == EAGAIN)
1334                                 return 0;
1335
1336                         return log_error_errno(errno, "Failed to read control group inotify events: %m");
1337                 }
1338
1339                 FOREACH_INOTIFY_EVENT(e, buffer, l) {
1340                         Unit *u;
1341
1342                         if (e->wd < 0)
1343                                 /* Queue overflow has no watch descriptor */
1344                                 continue;
1345
1346                         if (e->mask & IN_IGNORED)
1347                                 /* The watch was just removed */
1348                                 continue;
1349
1350                         u = hashmap_get(m->cgroup_inotify_wd_unit, INT_TO_PTR(e->wd));
1351                         if (!u) /* Not that inotify might deliver
1352                                  * events for a watch even after it
1353                                  * was removed, because it was queued
1354                                  * before the removal. Let's ignore
1355                                  * this here safely. */
1356                                 continue;
1357
1358                         (void) unit_notify_cgroup_empty(u);
1359                 }
1360         }
1361 }
1362 #endif // 0
1363
1364 int manager_setup_cgroup(Manager *m) {
1365         _cleanup_free_ char *path = NULL;
1366         CGroupController c;
1367         int r, unified;
1368         char *e;
1369
1370         assert(m);
1371
1372         /* 1. Determine hierarchy */
1373         m->cgroup_root = mfree(m->cgroup_root);
1374         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &m->cgroup_root);
1375         if (r < 0)
1376                 return log_error_errno(r, "Cannot determine cgroup we are running in: %m");
1377
1378 /// elogind does not support systemd scopes and slices
1379 #if 0
1380         /* Chop off the init scope, if we are already located in it */
1381         e = endswith(m->cgroup_root, "/" SPECIAL_INIT_SCOPE);
1382
1383         /* LEGACY: Also chop off the system slice if we are in
1384          * it. This is to support live upgrades from older systemd
1385          * versions where PID 1 was moved there. Also see
1386          * cg_get_root_path(). */
1387         if (!e && m->running_as == MANAGER_SYSTEM) {
1388                 e = endswith(m->cgroup_root, "/" SPECIAL_SYSTEM_SLICE);
1389                 if (!e)
1390                         e = endswith(m->cgroup_root, "/system"); /* even more legacy */
1391         }
1392         if (e)
1393                 *e = 0;
1394 #endif // 0
1395
1396         /* And make sure to store away the root value without trailing
1397          * slash, even for the root dir, so that we can easily prepend
1398          * it everywhere. */
1399         while ((e = endswith(m->cgroup_root, "/")))
1400                 *e = 0;
1401         log_debug_elogind("Cgroup Controller \"%s\" -> root \"%s\"",
1402                           SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root);
1403
1404         /* 2. Show data */
1405         r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, NULL, &path);
1406         if (r < 0)
1407                 return log_error_errno(r, "Cannot find cgroup mount point: %m");
1408
1409         unified = cg_unified();
1410         if (unified < 0)
1411                 return log_error_errno(r, "Couldn't determine if we are running in the unified hierarchy: %m");
1412         if (unified > 0)
1413                 log_debug("Unified cgroup hierarchy is located at %s.", path);
1414         else
1415                 log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER ". File system hierarchy is at %s.", path);
1416
1417         if (!m->test_run) {
1418                 const char *scope_path;
1419
1420                 /* 3. Install agent */
1421                 if (unified) {
1422
1423                         /* In the unified hierarchy we can can get
1424                          * cgroup empty notifications via inotify. */
1425
1426 /// elogind does not support the unified hierarchy, yet.
1427 #if 0
1428                         m->cgroup_inotify_event_source = sd_event_source_unref(m->cgroup_inotify_event_source);
1429                         safe_close(m->cgroup_inotify_fd);
1430
1431                         m->cgroup_inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
1432                         if (m->cgroup_inotify_fd < 0)
1433                                 return log_error_errno(errno, "Failed to create control group inotify object: %m");
1434
1435                         r = sd_event_add_io(m->event, &m->cgroup_inotify_event_source, m->cgroup_inotify_fd, EPOLLIN, on_cgroup_inotify_event, m);
1436                         if (r < 0)
1437                                 return log_error_errno(r, "Failed to watch control group inotify object: %m");
1438
1439                         r = sd_event_source_set_priority(m->cgroup_inotify_event_source, SD_EVENT_PRIORITY_IDLE - 5);
1440                         if (r < 0)
1441                                 return log_error_errno(r, "Failed to set priority of inotify event source: %m");
1442
1443                         (void) sd_event_source_set_description(m->cgroup_inotify_event_source, "cgroup-inotify");
1444
1445 #else
1446                         return log_error_errno(EOPNOTSUPP, "Unified cgroup hierarchy not supported: %m");
1447 #endif // 0
1448                 } else if (m->running_as == MANAGER_SYSTEM) {
1449
1450                         /* On the legacy hierarchy we only get
1451                          * notifications via cgroup agents. (Which
1452                          * isn't really reliable, since it does not
1453                          * generate events when control groups with
1454                          * children run empty. */
1455
1456                         r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, ELOGIND_CGROUP_AGENT_PATH);
1457                         if (r < 0)
1458                                 log_warning_errno(r, "Failed to install release agent, ignoring: %m");
1459                         else if (r > 0)
1460                                 log_debug("Installed release agent.");
1461                         else if (r == 0)
1462                                 log_debug("Release agent already installed.");
1463                 }
1464
1465 /// elogind is not meant to run in systemd init scope
1466 #if 0
1467                 /* 4. Make sure we are in the special "init.scope" unit in the root slice. */
1468                 scope_path = strjoina(m->cgroup_root, "/" SPECIAL_INIT_SCOPE);
1469                 r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, scope_path, 0);
1470 #else
1471                 if (streq(SYSTEMD_CGROUP_CONTROLLER, "name=elogind"))
1472                         // we are our own cgroup controller
1473                         scope_path = strjoina("");
1474                 else if (streq(m->cgroup_root, "/elogind"))
1475                         // root already is our cgroup
1476                         scope_path = strjoina(m->cgroup_root);
1477                 else
1478                         // we have to create our own group
1479                         scope_path = strjoina(m->cgroup_root, "/elogind");
1480                 r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, scope_path, 0);
1481 #endif // 0
1482                 if (r < 0)
1483                         return log_error_errno(r, "Failed to create %s control group: %m", scope_path);
1484                 log_debug_elogind("Created control group \"%s\"", scope_path);
1485
1486                 /* also, move all other userspace processes remaining
1487                  * in the root cgroup into that scope. */
1488                 if (!streq(m->cgroup_root, scope_path)) {
1489                         r = cg_migrate(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, SYSTEMD_CGROUP_CONTROLLER, scope_path, false);
1490                         if (r < 0)
1491                                 log_warning_errno(r, "Couldn't move remaining userspace processes, ignoring: %m");
1492                 }
1493
1494                 /* 5. And pin it, so that it cannot be unmounted */
1495                 safe_close(m->pin_cgroupfs_fd);
1496                 m->pin_cgroupfs_fd = open(path, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK);
1497                 if (m->pin_cgroupfs_fd < 0)
1498                         return log_error_errno(errno, "Failed to open pin file: %m");
1499
1500                 /* 6.  Always enable hierarchical support if it exists... */
1501                 if (!unified)
1502                         (void) cg_set_attribute("memory", "/", "memory.use_hierarchy", "1");
1503         }
1504
1505         /* 7. Figure out which controllers are supported */
1506         r = cg_mask_supported(&m->cgroup_supported);
1507         if (r < 0)
1508                 return log_error_errno(r, "Failed to determine supported controllers: %m");
1509
1510         for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++)
1511                 log_debug("Controller '%s' supported: %s", cgroup_controller_to_string(c), yes_no(m->cgroup_supported & c));
1512
1513         return 0;
1514 }
1515
1516 void manager_shutdown_cgroup(Manager *m, bool delete) {
1517         assert(m);
1518
1519         /* We can't really delete the group, since we are in it. But
1520          * let's trim it. */
1521         if (delete && m->cgroup_root)
1522                 (void) cg_trim(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, false);
1523
1524 /// elogind does not support the unified hierarchy, yet.
1525 #if 0
1526         m->cgroup_inotify_wd_unit = hashmap_free(m->cgroup_inotify_wd_unit);
1527
1528         m->cgroup_inotify_event_source = sd_event_source_unref(m->cgroup_inotify_event_source);
1529         m->cgroup_inotify_fd = safe_close(m->cgroup_inotify_fd);
1530 #endif // 0
1531
1532         m->pin_cgroupfs_fd = safe_close(m->pin_cgroupfs_fd);
1533
1534         m->cgroup_root = mfree(m->cgroup_root);
1535 }
1536
1537 #if 0 /// UNNEEDED by elogind
1538 Unit* manager_get_unit_by_cgroup(Manager *m, const char *cgroup) {
1539         char *p;
1540         Unit *u;
1541
1542         assert(m);
1543         assert(cgroup);
1544
1545         u = hashmap_get(m->cgroup_unit, cgroup);
1546         if (u)
1547                 return u;
1548
1549         p = strdupa(cgroup);
1550         for (;;) {
1551                 char *e;
1552
1553                 e = strrchr(p, '/');
1554                 if (!e || e == p)
1555                         return hashmap_get(m->cgroup_unit, SPECIAL_ROOT_SLICE);
1556
1557                 *e = 0;
1558
1559                 u = hashmap_get(m->cgroup_unit, p);
1560                 if (u)
1561                         return u;
1562         }
1563 }
1564
1565 Unit *manager_get_unit_by_pid_cgroup(Manager *m, pid_t pid) {
1566         _cleanup_free_ char *cgroup = NULL;
1567         int r;
1568
1569         assert(m);
1570
1571         if (pid <= 0)
1572                 return NULL;
1573
1574         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup);
1575         if (r < 0)
1576                 return NULL;
1577
1578         return manager_get_unit_by_cgroup(m, cgroup);
1579 }
1580
1581 Unit *manager_get_unit_by_pid(Manager *m, pid_t pid) {
1582         Unit *u;
1583
1584         assert(m);
1585
1586         if (pid <= 0)
1587                 return NULL;
1588
1589         if (pid == 1)
1590                 return hashmap_get(m->units, SPECIAL_INIT_SCOPE);
1591
1592         u = hashmap_get(m->watch_pids1, PID_TO_PTR(pid));
1593         if (u)
1594                 return u;
1595
1596         u = hashmap_get(m->watch_pids2, PID_TO_PTR(pid));
1597         if (u)
1598                 return u;
1599
1600         return manager_get_unit_by_pid_cgroup(m, pid);
1601 }
1602
1603 int manager_notify_cgroup_empty(Manager *m, const char *cgroup) {
1604         Unit *u;
1605
1606         assert(m);
1607         assert(cgroup);
1608
1609         u = manager_get_unit_by_cgroup(m, cgroup);
1610         if (!u)
1611                 return 0;
1612
1613         return unit_notify_cgroup_empty(u);
1614 }
1615
1616 int unit_get_memory_current(Unit *u, uint64_t *ret) {
1617         _cleanup_free_ char *v = NULL;
1618         int r;
1619
1620         assert(u);
1621         assert(ret);
1622
1623         if (!u->cgroup_path)
1624                 return -ENODATA;
1625
1626         if ((u->cgroup_realized_mask & CGROUP_MASK_MEMORY) == 0)
1627                 return -ENODATA;
1628
1629         if (cg_unified() <= 0)
1630                 r = cg_get_attribute("memory", u->cgroup_path, "memory.usage_in_bytes", &v);
1631         else
1632                 r = cg_get_attribute("memory", u->cgroup_path, "memory.current", &v);
1633         if (r == -ENOENT)
1634                 return -ENODATA;
1635         if (r < 0)
1636                 return r;
1637
1638         return safe_atou64(v, ret);
1639 }
1640
1641 int unit_get_tasks_current(Unit *u, uint64_t *ret) {
1642         _cleanup_free_ char *v = NULL;
1643         int r;
1644
1645         assert(u);
1646         assert(ret);
1647
1648         if (!u->cgroup_path)
1649                 return -ENODATA;
1650
1651         if ((u->cgroup_realized_mask & CGROUP_MASK_PIDS) == 0)
1652                 return -ENODATA;
1653
1654         r = cg_get_attribute("pids", u->cgroup_path, "pids.current", &v);
1655         if (r == -ENOENT)
1656                 return -ENODATA;
1657         if (r < 0)
1658                 return r;
1659
1660         return safe_atou64(v, ret);
1661 }
1662
1663 static int unit_get_cpu_usage_raw(Unit *u, nsec_t *ret) {
1664         _cleanup_free_ char *v = NULL;
1665         uint64_t ns;
1666         int r;
1667
1668         assert(u);
1669         assert(ret);
1670
1671         if (!u->cgroup_path)
1672                 return -ENODATA;
1673
1674         if ((u->cgroup_realized_mask & CGROUP_MASK_CPUACCT) == 0)
1675                 return -ENODATA;
1676
1677         r = cg_get_attribute("cpuacct", u->cgroup_path, "cpuacct.usage", &v);
1678         if (r == -ENOENT)
1679                 return -ENODATA;
1680         if (r < 0)
1681                 return r;
1682
1683         r = safe_atou64(v, &ns);
1684         if (r < 0)
1685                 return r;
1686
1687         *ret = ns;
1688         return 0;
1689 }
1690
1691 int unit_get_cpu_usage(Unit *u, nsec_t *ret) {
1692         nsec_t ns;
1693         int r;
1694
1695         r = unit_get_cpu_usage_raw(u, &ns);
1696         if (r < 0)
1697                 return r;
1698
1699         if (ns > u->cpuacct_usage_base)
1700                 ns -= u->cpuacct_usage_base;
1701         else
1702                 ns = 0;
1703
1704         *ret = ns;
1705         return 0;
1706 }
1707
1708 int unit_reset_cpu_usage(Unit *u) {
1709         nsec_t ns;
1710         int r;
1711
1712         assert(u);
1713
1714         r = unit_get_cpu_usage_raw(u, &ns);
1715         if (r < 0) {
1716                 u->cpuacct_usage_base = 0;
1717                 return r;
1718         }
1719
1720         u->cpuacct_usage_base = ns;
1721         return 0;
1722 }
1723
1724 bool unit_cgroup_delegate(Unit *u) {
1725         CGroupContext *c;
1726
1727         assert(u);
1728
1729         c = unit_get_cgroup_context(u);
1730         if (!c)
1731                 return false;
1732
1733         return c->delegate;
1734 }
1735
1736 void unit_invalidate_cgroup(Unit *u, CGroupMask m) {
1737         assert(u);
1738
1739         if (!UNIT_HAS_CGROUP_CONTEXT(u))
1740                 return;
1741
1742         if (m == 0)
1743                 return;
1744
1745         if ((u->cgroup_realized_mask & m) == 0)
1746                 return;
1747
1748         u->cgroup_realized_mask &= ~m;
1749         unit_add_to_cgroup_queue(u);
1750 }
1751
1752 void manager_invalidate_startup_units(Manager *m) {
1753         Iterator i;
1754         Unit *u;
1755
1756         assert(m);
1757
1758         SET_FOREACH(u, m->startup_units, i)
1759                 unit_invalidate_cgroup(u, CGROUP_MASK_CPU|CGROUP_MASK_BLKIO);
1760 }
1761
1762 static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = {
1763         [CGROUP_AUTO] = "auto",
1764         [CGROUP_CLOSED] = "closed",
1765         [CGROUP_STRICT] = "strict",
1766 };
1767
1768 DEFINE_STRING_TABLE_LOOKUP(cgroup_device_policy, CGroupDevicePolicy);
1769 #endif // 0