chiark / gitweb /
tree-wide: drop 'This file is part of systemd' blurb
[elogind.git] / src / core / cgroup.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3   Copyright 2013 Lennart Poettering
4 ***/
5
6 #include <fcntl.h>
7 #include <fnmatch.h>
8
9 #include "alloc-util.h"
10 //#include "blockdev-util.h"
11 //#include "bpf-firewall.h"
12 //#include "btrfs-util.h"
13 //#include "bus-error.h"
14 #include "cgroup-util.h"
15 #include "cgroup.h"
16 #include "fd-util.h"
17 #include "fileio.h"
18 #include "fs-util.h"
19 #include "parse-util.h"
20 #include "path-util.h"
21 #include "process-util.h"
22 //#include "procfs-util.h"
23 //#include "special.h"
24 #include "stdio-util.h"
25 #include "string-table.h"
26 #include "string-util.h"
27 #include "virt.h"
28
29 #define CGROUP_CPU_QUOTA_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC)
30
31 bool manager_owns_root_cgroup(Manager *m) {
32         assert(m);
33
34         /* Returns true if we are managing the root cgroup. Note that it isn't sufficient to just check whether the
35          * group root path equals "/" since that will also be the case if CLONE_NEWCGROUP is in the mix. Since there's
36          * appears to be no nice way to detect whether we are in a CLONE_NEWCGROUP namespace we instead just check if
37          * we run in any kind of container virtualization. */
38
39         if (detect_container() > 0)
40                 return false;
41
42         return empty_or_root(m->cgroup_root);
43 }
44
45 #if 0 /// UNNEEDED by elogind
46 bool unit_has_root_cgroup(Unit *u) {
47         assert(u);
48
49         /* Returns whether this unit manages the root cgroup. This will return true if this unit is the root slice and
50          * the manager manages the root cgroup. */
51
52         if (!manager_owns_root_cgroup(u->manager))
53                 return false;
54
55         return unit_has_name(u, SPECIAL_ROOT_SLICE);
56 }
57
58 static void cgroup_compat_warn(void) {
59         static bool cgroup_compat_warned = false;
60
61         if (cgroup_compat_warned)
62                 return;
63
64         log_warning("cgroup compatibility translation between legacy and unified hierarchy settings activated. "
65                     "See cgroup-compat debug messages for details.");
66
67         cgroup_compat_warned = true;
68 }
69
70 #define log_cgroup_compat(unit, fmt, ...) do {                                  \
71                 cgroup_compat_warn();                                           \
72                 log_unit_debug(unit, "cgroup-compat: " fmt, ##__VA_ARGS__);     \
73         } while (false)
74
75 void cgroup_context_init(CGroupContext *c) {
76         assert(c);
77
78         /* Initialize everything to the kernel defaults, assuming the
79          * structure is preinitialized to 0 */
80
81         c->cpu_weight = CGROUP_WEIGHT_INVALID;
82         c->startup_cpu_weight = CGROUP_WEIGHT_INVALID;
83         c->cpu_quota_per_sec_usec = USEC_INFINITY;
84
85         c->cpu_shares = CGROUP_CPU_SHARES_INVALID;
86         c->startup_cpu_shares = CGROUP_CPU_SHARES_INVALID;
87
88         c->memory_high = CGROUP_LIMIT_MAX;
89         c->memory_max = CGROUP_LIMIT_MAX;
90         c->memory_swap_max = CGROUP_LIMIT_MAX;
91
92         c->memory_limit = CGROUP_LIMIT_MAX;
93
94         c->io_weight = CGROUP_WEIGHT_INVALID;
95         c->startup_io_weight = CGROUP_WEIGHT_INVALID;
96
97         c->blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID;
98         c->startup_blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID;
99
100         c->tasks_max = (uint64_t) -1;
101 }
102
103 void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a) {
104         assert(c);
105         assert(a);
106
107         LIST_REMOVE(device_allow, c->device_allow, a);
108         free(a->path);
109         free(a);
110 }
111
112 void cgroup_context_free_io_device_weight(CGroupContext *c, CGroupIODeviceWeight *w) {
113         assert(c);
114         assert(w);
115
116         LIST_REMOVE(device_weights, c->io_device_weights, w);
117         free(w->path);
118         free(w);
119 }
120
121 void cgroup_context_free_io_device_limit(CGroupContext *c, CGroupIODeviceLimit *l) {
122         assert(c);
123         assert(l);
124
125         LIST_REMOVE(device_limits, c->io_device_limits, l);
126         free(l->path);
127         free(l);
128 }
129
130 void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w) {
131         assert(c);
132         assert(w);
133
134         LIST_REMOVE(device_weights, c->blockio_device_weights, w);
135         free(w->path);
136         free(w);
137 }
138
139 void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b) {
140         assert(c);
141         assert(b);
142
143         LIST_REMOVE(device_bandwidths, c->blockio_device_bandwidths, b);
144         free(b->path);
145         free(b);
146 }
147
148 void cgroup_context_done(CGroupContext *c) {
149         assert(c);
150
151         while (c->io_device_weights)
152                 cgroup_context_free_io_device_weight(c, c->io_device_weights);
153
154         while (c->io_device_limits)
155                 cgroup_context_free_io_device_limit(c, c->io_device_limits);
156
157         while (c->blockio_device_weights)
158                 cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
159
160         while (c->blockio_device_bandwidths)
161                 cgroup_context_free_blockio_device_bandwidth(c, c->blockio_device_bandwidths);
162
163         while (c->device_allow)
164                 cgroup_context_free_device_allow(c, c->device_allow);
165
166         c->ip_address_allow = ip_address_access_free_all(c->ip_address_allow);
167         c->ip_address_deny = ip_address_access_free_all(c->ip_address_deny);
168 }
169
170 void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
171         CGroupIODeviceLimit *il;
172         CGroupIODeviceWeight *iw;
173         CGroupBlockIODeviceBandwidth *b;
174         CGroupBlockIODeviceWeight *w;
175         CGroupDeviceAllow *a;
176         IPAddressAccessItem *iaai;
177         char u[FORMAT_TIMESPAN_MAX];
178
179         assert(c);
180         assert(f);
181
182         prefix = strempty(prefix);
183
184         fprintf(f,
185                 "%sCPUAccounting=%s\n"
186                 "%sIOAccounting=%s\n"
187                 "%sBlockIOAccounting=%s\n"
188                 "%sMemoryAccounting=%s\n"
189                 "%sTasksAccounting=%s\n"
190                 "%sIPAccounting=%s\n"
191                 "%sCPUWeight=%" PRIu64 "\n"
192                 "%sStartupCPUWeight=%" PRIu64 "\n"
193                 "%sCPUShares=%" PRIu64 "\n"
194                 "%sStartupCPUShares=%" PRIu64 "\n"
195                 "%sCPUQuotaPerSecSec=%s\n"
196                 "%sIOWeight=%" PRIu64 "\n"
197                 "%sStartupIOWeight=%" PRIu64 "\n"
198                 "%sBlockIOWeight=%" PRIu64 "\n"
199                 "%sStartupBlockIOWeight=%" PRIu64 "\n"
200                 "%sMemoryLow=%" PRIu64 "\n"
201                 "%sMemoryHigh=%" PRIu64 "\n"
202                 "%sMemoryMax=%" PRIu64 "\n"
203                 "%sMemorySwapMax=%" PRIu64 "\n"
204                 "%sMemoryLimit=%" PRIu64 "\n"
205                 "%sTasksMax=%" PRIu64 "\n"
206                 "%sDevicePolicy=%s\n"
207                 "%sDelegate=%s\n",
208                 prefix, yes_no(c->cpu_accounting),
209                 prefix, yes_no(c->io_accounting),
210                 prefix, yes_no(c->blockio_accounting),
211                 prefix, yes_no(c->memory_accounting),
212                 prefix, yes_no(c->tasks_accounting),
213                 prefix, yes_no(c->ip_accounting),
214                 prefix, c->cpu_weight,
215                 prefix, c->startup_cpu_weight,
216                 prefix, c->cpu_shares,
217                 prefix, c->startup_cpu_shares,
218                 prefix, format_timespan(u, sizeof(u), c->cpu_quota_per_sec_usec, 1),
219                 prefix, c->io_weight,
220                 prefix, c->startup_io_weight,
221                 prefix, c->blockio_weight,
222                 prefix, c->startup_blockio_weight,
223                 prefix, c->memory_low,
224                 prefix, c->memory_high,
225                 prefix, c->memory_max,
226                 prefix, c->memory_swap_max,
227                 prefix, c->memory_limit,
228                 prefix, c->tasks_max,
229                 prefix, cgroup_device_policy_to_string(c->device_policy),
230                 prefix, yes_no(c->delegate));
231
232         if (c->delegate) {
233                 _cleanup_free_ char *t = NULL;
234
235                 (void) cg_mask_to_string(c->delegate_controllers, &t);
236
237                 fprintf(f, "%sDelegateControllers=%s\n",
238                         prefix,
239                         strempty(t));
240         }
241
242         LIST_FOREACH(device_allow, a, c->device_allow)
243                 fprintf(f,
244                         "%sDeviceAllow=%s %s%s%s\n",
245                         prefix,
246                         a->path,
247                         a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
248
249         LIST_FOREACH(device_weights, iw, c->io_device_weights)
250                 fprintf(f,
251                         "%sIODeviceWeight=%s %" PRIu64,
252                         prefix,
253                         iw->path,
254                         iw->weight);
255
256         LIST_FOREACH(device_limits, il, c->io_device_limits) {
257                 char buf[FORMAT_BYTES_MAX];
258                 CGroupIOLimitType type;
259
260                 for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
261                         if (il->limits[type] != cgroup_io_limit_defaults[type])
262                                 fprintf(f,
263                                         "%s%s=%s %s\n",
264                                         prefix,
265                                         cgroup_io_limit_type_to_string(type),
266                                         il->path,
267                                         format_bytes(buf, sizeof(buf), il->limits[type]));
268         }
269
270         LIST_FOREACH(device_weights, w, c->blockio_device_weights)
271                 fprintf(f,
272                         "%sBlockIODeviceWeight=%s %" PRIu64,
273                         prefix,
274                         w->path,
275                         w->weight);
276
277         LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
278                 char buf[FORMAT_BYTES_MAX];
279
280                 if (b->rbps != CGROUP_LIMIT_MAX)
281                         fprintf(f,
282                                 "%sBlockIOReadBandwidth=%s %s\n",
283                                 prefix,
284                                 b->path,
285                                 format_bytes(buf, sizeof(buf), b->rbps));
286                 if (b->wbps != CGROUP_LIMIT_MAX)
287                         fprintf(f,
288                                 "%sBlockIOWriteBandwidth=%s %s\n",
289                                 prefix,
290                                 b->path,
291                                 format_bytes(buf, sizeof(buf), b->wbps));
292         }
293
294         LIST_FOREACH(items, iaai, c->ip_address_allow) {
295                 _cleanup_free_ char *k = NULL;
296
297                 (void) in_addr_to_string(iaai->family, &iaai->address, &k);
298                 fprintf(f, "%sIPAddressAllow=%s/%u\n", prefix, strnull(k), iaai->prefixlen);
299         }
300
301         LIST_FOREACH(items, iaai, c->ip_address_deny) {
302                 _cleanup_free_ char *k = NULL;
303
304                 (void) in_addr_to_string(iaai->family, &iaai->address, &k);
305                 fprintf(f, "%sIPAddressDeny=%s/%u\n", prefix, strnull(k), iaai->prefixlen);
306         }
307 }
308
309 static int lookup_block_device(const char *p, dev_t *ret) {
310         struct stat st;
311         int r;
312
313         assert(p);
314         assert(ret);
315
316         if (stat(p, &st) < 0)
317                 return log_warning_errno(errno, "Couldn't stat device '%s': %m", p);
318
319         if (S_ISBLK(st.st_mode))
320                 *ret = st.st_rdev;
321         else if (major(st.st_dev) != 0)
322                 *ret = st.st_dev; /* If this is not a device node then use the block device this file is stored on */
323         else {
324                 /* If this is btrfs, getting the backing block device is a bit harder */
325                 r = btrfs_get_block_device(p, ret);
326                 if (r < 0 && r != -ENOTTY)
327                         return log_warning_errno(r, "Failed to determine block device backing btrfs file system '%s': %m", p);
328                 if (r == -ENOTTY) {
329                         log_warning("'%s' is not a block device node, and file system block device cannot be determined or is not local.", p);
330                         return -ENODEV;
331                 }
332         }
333
334         /* If this is a LUKS device, try to get the originating block device */
335         (void) block_get_originating(*ret, ret);
336
337         /* If this is a partition, try to get the originating block device */
338         (void) block_get_whole_disk(*ret, ret);
339         return 0;
340 }
341
342 static int whitelist_device(const char *path, const char *node, const char *acc) {
343         char buf[2+DECIMAL_STR_MAX(dev_t)*2+2+4];
344         struct stat st;
345         bool ignore_notfound;
346         int r;
347
348         assert(path);
349         assert(acc);
350
351         if (node[0] == '-') {
352                 /* Non-existent paths starting with "-" must be silently ignored */
353                 node++;
354                 ignore_notfound = true;
355         } else
356                 ignore_notfound = false;
357
358         if (stat(node, &st) < 0) {
359                 if (errno == ENOENT && ignore_notfound)
360                         return 0;
361
362                 return log_warning_errno(errno, "Couldn't stat device %s: %m", node);
363         }
364
365         if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
366                 log_warning("%s is not a device.", node);
367                 return -ENODEV;
368         }
369
370         sprintf(buf,
371                 "%c %u:%u %s",
372                 S_ISCHR(st.st_mode) ? 'c' : 'b',
373                 major(st.st_rdev), minor(st.st_rdev),
374                 acc);
375
376         r = cg_set_attribute("devices", path, "devices.allow", buf);
377         if (r < 0)
378                 log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
379                                "Failed to set devices.allow on %s: %m", path);
380
381         return r;
382 }
383
384 static int whitelist_major(const char *path, const char *name, char type, const char *acc) {
385         _cleanup_fclose_ FILE *f = NULL;
386         char line[LINE_MAX];
387         bool good = false;
388         int r;
389
390         assert(path);
391         assert(acc);
392         assert(IN_SET(type, 'b', 'c'));
393
394         f = fopen("/proc/devices", "re");
395         if (!f)
396                 return log_warning_errno(errno, "Cannot open /proc/devices to resolve %s (%c): %m", name, type);
397
398         FOREACH_LINE(line, f, goto fail) {
399                 char buf[2+DECIMAL_STR_MAX(unsigned)+3+4], *p, *w;
400                 unsigned maj;
401
402                 truncate_nl(line);
403
404                 if (type == 'c' && streq(line, "Character devices:")) {
405                         good = true;
406                         continue;
407                 }
408
409                 if (type == 'b' && streq(line, "Block devices:")) {
410                         good = true;
411                         continue;
412                 }
413
414                 if (isempty(line)) {
415                         good = false;
416                         continue;
417                 }
418
419                 if (!good)
420                         continue;
421
422                 p = strstrip(line);
423
424                 w = strpbrk(p, WHITESPACE);
425                 if (!w)
426                         continue;
427                 *w = 0;
428
429                 r = safe_atou(p, &maj);
430                 if (r < 0)
431                         continue;
432                 if (maj <= 0)
433                         continue;
434
435                 w++;
436                 w += strspn(w, WHITESPACE);
437
438                 if (fnmatch(name, w, 0) != 0)
439                         continue;
440
441                 sprintf(buf,
442                         "%c %u:* %s",
443                         type,
444                         maj,
445                         acc);
446
447                 r = cg_set_attribute("devices", path, "devices.allow", buf);
448                 if (r < 0)
449                         log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
450                                        "Failed to set devices.allow on %s: %m", path);
451         }
452
453         return 0;
454
455 fail:
456         return log_warning_errno(errno, "Failed to read /proc/devices: %m");
457 }
458
459 static bool cgroup_context_has_cpu_weight(CGroupContext *c) {
460         return c->cpu_weight != CGROUP_WEIGHT_INVALID ||
461                 c->startup_cpu_weight != CGROUP_WEIGHT_INVALID;
462 }
463
464 static bool cgroup_context_has_cpu_shares(CGroupContext *c) {
465         return c->cpu_shares != CGROUP_CPU_SHARES_INVALID ||
466                 c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID;
467 }
468
469 static uint64_t cgroup_context_cpu_weight(CGroupContext *c, ManagerState state) {
470         if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) &&
471             c->startup_cpu_weight != CGROUP_WEIGHT_INVALID)
472                 return c->startup_cpu_weight;
473         else if (c->cpu_weight != CGROUP_WEIGHT_INVALID)
474                 return c->cpu_weight;
475         else
476                 return CGROUP_WEIGHT_DEFAULT;
477 }
478
479 static uint64_t cgroup_context_cpu_shares(CGroupContext *c, ManagerState state) {
480         if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) &&
481             c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID)
482                 return c->startup_cpu_shares;
483         else if (c->cpu_shares != CGROUP_CPU_SHARES_INVALID)
484                 return c->cpu_shares;
485         else
486                 return CGROUP_CPU_SHARES_DEFAULT;
487 }
488
489 static void cgroup_apply_unified_cpu_config(Unit *u, uint64_t weight, uint64_t quota) {
490         char buf[MAX(DECIMAL_STR_MAX(uint64_t) + 1, (DECIMAL_STR_MAX(usec_t) + 1) * 2)];
491         int r;
492
493         xsprintf(buf, "%" PRIu64 "\n", weight);
494         r = cg_set_attribute("cpu", u->cgroup_path, "cpu.weight", buf);
495         if (r < 0)
496                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
497                               "Failed to set cpu.weight: %m");
498
499         if (quota != USEC_INFINITY)
500                 xsprintf(buf, USEC_FMT " " USEC_FMT "\n",
501                          quota * CGROUP_CPU_QUOTA_PERIOD_USEC / USEC_PER_SEC, CGROUP_CPU_QUOTA_PERIOD_USEC);
502         else
503                 xsprintf(buf, "max " USEC_FMT "\n", CGROUP_CPU_QUOTA_PERIOD_USEC);
504
505         r = cg_set_attribute("cpu", u->cgroup_path, "cpu.max", buf);
506
507         if (r < 0)
508                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
509                               "Failed to set cpu.max: %m");
510 }
511
512 static void cgroup_apply_legacy_cpu_config(Unit *u, uint64_t shares, uint64_t quota) {
513         char buf[MAX(DECIMAL_STR_MAX(uint64_t), DECIMAL_STR_MAX(usec_t)) + 1];
514         int r;
515
516         xsprintf(buf, "%" PRIu64 "\n", shares);
517         r = cg_set_attribute("cpu", u->cgroup_path, "cpu.shares", buf);
518         if (r < 0)
519                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
520                               "Failed to set cpu.shares: %m");
521
522         xsprintf(buf, USEC_FMT "\n", CGROUP_CPU_QUOTA_PERIOD_USEC);
523         r = cg_set_attribute("cpu", u->cgroup_path, "cpu.cfs_period_us", buf);
524         if (r < 0)
525                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
526                               "Failed to set cpu.cfs_period_us: %m");
527
528         if (quota != USEC_INFINITY) {
529                 xsprintf(buf, USEC_FMT "\n", quota * CGROUP_CPU_QUOTA_PERIOD_USEC / USEC_PER_SEC);
530                 r = cg_set_attribute("cpu", u->cgroup_path, "cpu.cfs_quota_us", buf);
531         } else
532                 r = cg_set_attribute("cpu", u->cgroup_path, "cpu.cfs_quota_us", "-1");
533         if (r < 0)
534                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
535                               "Failed to set cpu.cfs_quota_us: %m");
536 }
537
538 static uint64_t cgroup_cpu_shares_to_weight(uint64_t shares) {
539         return CLAMP(shares * CGROUP_WEIGHT_DEFAULT / CGROUP_CPU_SHARES_DEFAULT,
540                      CGROUP_WEIGHT_MIN, CGROUP_WEIGHT_MAX);
541 }
542
543 static uint64_t cgroup_cpu_weight_to_shares(uint64_t weight) {
544         return CLAMP(weight * CGROUP_CPU_SHARES_DEFAULT / CGROUP_WEIGHT_DEFAULT,
545                      CGROUP_CPU_SHARES_MIN, CGROUP_CPU_SHARES_MAX);
546 }
547
548 static bool cgroup_context_has_io_config(CGroupContext *c) {
549         return c->io_accounting ||
550                 c->io_weight != CGROUP_WEIGHT_INVALID ||
551                 c->startup_io_weight != CGROUP_WEIGHT_INVALID ||
552                 c->io_device_weights ||
553                 c->io_device_limits;
554 }
555
556 static bool cgroup_context_has_blockio_config(CGroupContext *c) {
557         return c->blockio_accounting ||
558                 c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ||
559                 c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ||
560                 c->blockio_device_weights ||
561                 c->blockio_device_bandwidths;
562 }
563
564 static uint64_t cgroup_context_io_weight(CGroupContext *c, ManagerState state) {
565         if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) &&
566             c->startup_io_weight != CGROUP_WEIGHT_INVALID)
567                 return c->startup_io_weight;
568         else if (c->io_weight != CGROUP_WEIGHT_INVALID)
569                 return c->io_weight;
570         else
571                 return CGROUP_WEIGHT_DEFAULT;
572 }
573
574 static uint64_t cgroup_context_blkio_weight(CGroupContext *c, ManagerState state) {
575         if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) &&
576             c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID)
577                 return c->startup_blockio_weight;
578         else if (c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID)
579                 return c->blockio_weight;
580         else
581                 return CGROUP_BLKIO_WEIGHT_DEFAULT;
582 }
583
584 static uint64_t cgroup_weight_blkio_to_io(uint64_t blkio_weight) {
585         return CLAMP(blkio_weight * CGROUP_WEIGHT_DEFAULT / CGROUP_BLKIO_WEIGHT_DEFAULT,
586                      CGROUP_WEIGHT_MIN, CGROUP_WEIGHT_MAX);
587 }
588
589 static uint64_t cgroup_weight_io_to_blkio(uint64_t io_weight) {
590         return CLAMP(io_weight * CGROUP_BLKIO_WEIGHT_DEFAULT / CGROUP_WEIGHT_DEFAULT,
591                      CGROUP_BLKIO_WEIGHT_MIN, CGROUP_BLKIO_WEIGHT_MAX);
592 }
593
594 static void cgroup_apply_io_device_weight(Unit *u, const char *dev_path, uint64_t io_weight) {
595         char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1];
596         dev_t dev;
597         int r;
598
599         r = lookup_block_device(dev_path, &dev);
600         if (r < 0)
601                 return;
602
603         xsprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), io_weight);
604         r = cg_set_attribute("io", u->cgroup_path, "io.weight", buf);
605         if (r < 0)
606                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
607                               "Failed to set io.weight: %m");
608 }
609
610 static void cgroup_apply_blkio_device_weight(Unit *u, const char *dev_path, uint64_t blkio_weight) {
611         char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1];
612         dev_t dev;
613         int r;
614
615         r = lookup_block_device(dev_path, &dev);
616         if (r < 0)
617                 return;
618
619         xsprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), blkio_weight);
620         r = cg_set_attribute("blkio", u->cgroup_path, "blkio.weight_device", buf);
621         if (r < 0)
622                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
623                               "Failed to set blkio.weight_device: %m");
624 }
625
626 static void cgroup_apply_io_device_limit(Unit *u, const char *dev_path, uint64_t *limits) {
627         char limit_bufs[_CGROUP_IO_LIMIT_TYPE_MAX][DECIMAL_STR_MAX(uint64_t)];
628         char buf[DECIMAL_STR_MAX(dev_t)*2+2+(6+DECIMAL_STR_MAX(uint64_t)+1)*4];
629         CGroupIOLimitType type;
630         dev_t dev;
631         int r;
632
633         r = lookup_block_device(dev_path, &dev);
634         if (r < 0)
635                 return;
636
637         for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
638                 if (limits[type] != cgroup_io_limit_defaults[type])
639                         xsprintf(limit_bufs[type], "%" PRIu64, limits[type]);
640                 else
641                         xsprintf(limit_bufs[type], "%s", limits[type] == CGROUP_LIMIT_MAX ? "max" : "0");
642
643         xsprintf(buf, "%u:%u rbps=%s wbps=%s riops=%s wiops=%s\n", major(dev), minor(dev),
644                  limit_bufs[CGROUP_IO_RBPS_MAX], limit_bufs[CGROUP_IO_WBPS_MAX],
645                  limit_bufs[CGROUP_IO_RIOPS_MAX], limit_bufs[CGROUP_IO_WIOPS_MAX]);
646         r = cg_set_attribute("io", u->cgroup_path, "io.max", buf);
647         if (r < 0)
648                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
649                               "Failed to set io.max: %m");
650 }
651
652 static void cgroup_apply_blkio_device_limit(Unit *u, const char *dev_path, uint64_t rbps, uint64_t wbps) {
653         char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1];
654         dev_t dev;
655         int r;
656
657         r = lookup_block_device(dev_path, &dev);
658         if (r < 0)
659                 return;
660
661         sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), rbps);
662         r = cg_set_attribute("blkio", u->cgroup_path, "blkio.throttle.read_bps_device", buf);
663         if (r < 0)
664                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
665                               "Failed to set blkio.throttle.read_bps_device: %m");
666
667         sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), wbps);
668         r = cg_set_attribute("blkio", u->cgroup_path, "blkio.throttle.write_bps_device", buf);
669         if (r < 0)
670                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
671                               "Failed to set blkio.throttle.write_bps_device: %m");
672 }
673
674 static bool cgroup_context_has_unified_memory_config(CGroupContext *c) {
675         return c->memory_low > 0 || c->memory_high != CGROUP_LIMIT_MAX || c->memory_max != CGROUP_LIMIT_MAX || c->memory_swap_max != CGROUP_LIMIT_MAX;
676 }
677
678 static void cgroup_apply_unified_memory_limit(Unit *u, const char *file, uint64_t v) {
679         char buf[DECIMAL_STR_MAX(uint64_t) + 1] = "max";
680         int r;
681
682         if (v != CGROUP_LIMIT_MAX)
683                 xsprintf(buf, "%" PRIu64 "\n", v);
684
685         r = cg_set_attribute("memory", u->cgroup_path, file, buf);
686         if (r < 0)
687                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
688                               "Failed to set %s: %m", file);
689 }
690
691 static void cgroup_apply_firewall(Unit *u) {
692         assert(u);
693
694         /* Best-effort: let's apply IP firewalling and/or accounting if that's enabled */
695
696         if (bpf_firewall_compile(u) < 0)
697                 return;
698
699         (void) bpf_firewall_install(u);
700 }
701
702 static void cgroup_context_apply(
703                 Unit *u,
704                 CGroupMask apply_mask,
705                 bool apply_bpf,
706                 ManagerState state) {
707
708         const char *path;
709         CGroupContext *c;
710         bool is_root;
711         int r;
712
713         assert(u);
714
715         /* Nothing to do? Exit early! */
716         if (apply_mask == 0 && !apply_bpf)
717                 return;
718
719         /* Some cgroup attributes are not supported on the root cgroup, hence silently ignore */
720         is_root = unit_has_root_cgroup(u);
721
722         assert_se(c = unit_get_cgroup_context(u));
723         assert_se(path = u->cgroup_path);
724
725         if (is_root) /* Make sure we don't try to display messages with an empty path. */
726                 path = "/";
727
728         /* We generally ignore errors caused by read-only mounted
729          * cgroup trees (assuming we are running in a container then),
730          * and missing cgroups, i.e. EROFS and ENOENT. */
731
732         if ((apply_mask & CGROUP_MASK_CPU) && !is_root) {
733                 bool has_weight, has_shares;
734
735                 has_weight = cgroup_context_has_cpu_weight(c);
736                 has_shares = cgroup_context_has_cpu_shares(c);
737
738                 if (cg_all_unified() > 0) {
739                         uint64_t weight;
740
741                         if (has_weight)
742                                 weight = cgroup_context_cpu_weight(c, state);
743                         else if (has_shares) {
744                                 uint64_t shares = cgroup_context_cpu_shares(c, state);
745
746                                 weight = cgroup_cpu_shares_to_weight(shares);
747
748                                 log_cgroup_compat(u, "Applying [Startup]CpuShares %" PRIu64 " as [Startup]CpuWeight %" PRIu64 " on %s",
749                                                   shares, weight, path);
750                         } else
751                                 weight = CGROUP_WEIGHT_DEFAULT;
752
753                         cgroup_apply_unified_cpu_config(u, weight, c->cpu_quota_per_sec_usec);
754                 } else {
755                         uint64_t shares;
756
757                         if (has_weight) {
758                                 uint64_t weight = cgroup_context_cpu_weight(c, state);
759
760                                 shares = cgroup_cpu_weight_to_shares(weight);
761
762                                 log_cgroup_compat(u, "Applying [Startup]CpuWeight %" PRIu64 " as [Startup]CpuShares %" PRIu64 " on %s",
763                                                   weight, shares, path);
764                         } else if (has_shares)
765                                 shares = cgroup_context_cpu_shares(c, state);
766                         else
767                                 shares = CGROUP_CPU_SHARES_DEFAULT;
768
769                         cgroup_apply_legacy_cpu_config(u, shares, c->cpu_quota_per_sec_usec);
770                 }
771         }
772
773         if (apply_mask & CGROUP_MASK_IO) {
774                 bool has_io = cgroup_context_has_io_config(c);
775                 bool has_blockio = cgroup_context_has_blockio_config(c);
776
777                 if (!is_root) {
778                         char buf[8+DECIMAL_STR_MAX(uint64_t)+1];
779                         uint64_t weight;
780
781                         if (has_io)
782                                 weight = cgroup_context_io_weight(c, state);
783                         else if (has_blockio) {
784                                 uint64_t blkio_weight = cgroup_context_blkio_weight(c, state);
785
786                                 weight = cgroup_weight_blkio_to_io(blkio_weight);
787
788                                 log_cgroup_compat(u, "Applying [Startup]BlockIOWeight %" PRIu64 " as [Startup]IOWeight %" PRIu64,
789                                                   blkio_weight, weight);
790                         } else
791                                 weight = CGROUP_WEIGHT_DEFAULT;
792
793                         xsprintf(buf, "default %" PRIu64 "\n", weight);
794                         r = cg_set_attribute("io", path, "io.weight", buf);
795                         if (r < 0)
796                                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
797                                               "Failed to set io.weight: %m");
798
799                         if (has_io) {
800                                 CGroupIODeviceWeight *w;
801
802                                 /* FIXME: no way to reset this list */
803                                 LIST_FOREACH(device_weights, w, c->io_device_weights)
804                                         cgroup_apply_io_device_weight(u, w->path, w->weight);
805                         } else if (has_blockio) {
806                                 CGroupBlockIODeviceWeight *w;
807
808                                 /* FIXME: no way to reset this list */
809                                 LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
810                                         weight = cgroup_weight_blkio_to_io(w->weight);
811
812                                         log_cgroup_compat(u, "Applying BlockIODeviceWeight %" PRIu64 " as IODeviceWeight %" PRIu64 " for %s",
813                                                           w->weight, weight, w->path);
814
815                                         cgroup_apply_io_device_weight(u, w->path, weight);
816                                 }
817                         }
818                 }
819
820                 /* Apply limits and free ones without config. */
821                 if (has_io) {
822                         CGroupIODeviceLimit *l;
823
824                         LIST_FOREACH(device_limits, l, c->io_device_limits)
825                                 cgroup_apply_io_device_limit(u, l->path, l->limits);
826
827                 } else if (has_blockio) {
828                         CGroupBlockIODeviceBandwidth *b;
829
830                         LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
831                                 uint64_t limits[_CGROUP_IO_LIMIT_TYPE_MAX];
832                                 CGroupIOLimitType type;
833
834                                 for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
835                                         limits[type] = cgroup_io_limit_defaults[type];
836
837                                 limits[CGROUP_IO_RBPS_MAX] = b->rbps;
838                                 limits[CGROUP_IO_WBPS_MAX] = b->wbps;
839
840                                 log_cgroup_compat(u, "Applying BlockIO{Read|Write}Bandwidth %" PRIu64 " %" PRIu64 " as IO{Read|Write}BandwidthMax for %s",
841                                                   b->rbps, b->wbps, b->path);
842
843                                 cgroup_apply_io_device_limit(u, b->path, limits);
844                         }
845                 }
846         }
847
848         if (apply_mask & CGROUP_MASK_BLKIO) {
849                 bool has_io = cgroup_context_has_io_config(c);
850                 bool has_blockio = cgroup_context_has_blockio_config(c);
851
852                 if (!is_root) {
853                         char buf[DECIMAL_STR_MAX(uint64_t)+1];
854                         uint64_t weight;
855
856                         if (has_io) {
857                                 uint64_t io_weight = cgroup_context_io_weight(c, state);
858
859                                 weight = cgroup_weight_io_to_blkio(cgroup_context_io_weight(c, state));
860
861                                 log_cgroup_compat(u, "Applying [Startup]IOWeight %" PRIu64 " as [Startup]BlockIOWeight %" PRIu64,
862                                                   io_weight, weight);
863                         } else if (has_blockio)
864                                 weight = cgroup_context_blkio_weight(c, state);
865                         else
866                                 weight = CGROUP_BLKIO_WEIGHT_DEFAULT;
867
868                         xsprintf(buf, "%" PRIu64 "\n", weight);
869                         r = cg_set_attribute("blkio", path, "blkio.weight", buf);
870                         if (r < 0)
871                                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
872                                               "Failed to set blkio.weight: %m");
873
874                         if (has_io) {
875                                 CGroupIODeviceWeight *w;
876
877                                 /* FIXME: no way to reset this list */
878                                 LIST_FOREACH(device_weights, w, c->io_device_weights) {
879                                         weight = cgroup_weight_io_to_blkio(w->weight);
880
881                                         log_cgroup_compat(u, "Applying IODeviceWeight %" PRIu64 " as BlockIODeviceWeight %" PRIu64 " for %s",
882                                                           w->weight, weight, w->path);
883
884                                         cgroup_apply_blkio_device_weight(u, w->path, weight);
885                                 }
886                         } else if (has_blockio) {
887                                 CGroupBlockIODeviceWeight *w;
888
889                                 /* FIXME: no way to reset this list */
890                                 LIST_FOREACH(device_weights, w, c->blockio_device_weights)
891                                         cgroup_apply_blkio_device_weight(u, w->path, w->weight);
892                         }
893                 }
894
895                 /* Apply limits and free ones without config. */
896                 if (has_io) {
897                         CGroupIODeviceLimit *l;
898
899                         LIST_FOREACH(device_limits, l, c->io_device_limits) {
900                                 log_cgroup_compat(u, "Applying IO{Read|Write}Bandwidth %" PRIu64 " %" PRIu64 " as BlockIO{Read|Write}BandwidthMax for %s",
901                                                   l->limits[CGROUP_IO_RBPS_MAX], l->limits[CGROUP_IO_WBPS_MAX], l->path);
902
903                                 cgroup_apply_blkio_device_limit(u, l->path, l->limits[CGROUP_IO_RBPS_MAX], l->limits[CGROUP_IO_WBPS_MAX]);
904                         }
905                 } else if (has_blockio) {
906                         CGroupBlockIODeviceBandwidth *b;
907
908                         LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths)
909                                 cgroup_apply_blkio_device_limit(u, b->path, b->rbps, b->wbps);
910                 }
911         }
912
913         if ((apply_mask & CGROUP_MASK_MEMORY) && !is_root) {
914                 if (cg_all_unified() > 0) {
915                         uint64_t max, swap_max = CGROUP_LIMIT_MAX;
916
917                         if (cgroup_context_has_unified_memory_config(c)) {
918                                 max = c->memory_max;
919                                 swap_max = c->memory_swap_max;
920                         } else {
921                                 max = c->memory_limit;
922
923                                 if (max != CGROUP_LIMIT_MAX)
924                                         log_cgroup_compat(u, "Applying MemoryLimit %" PRIu64 " as MemoryMax", max);
925                         }
926
927                         cgroup_apply_unified_memory_limit(u, "memory.low", c->memory_low);
928                         cgroup_apply_unified_memory_limit(u, "memory.high", c->memory_high);
929                         cgroup_apply_unified_memory_limit(u, "memory.max", max);
930                         cgroup_apply_unified_memory_limit(u, "memory.swap.max", swap_max);
931                 } else {
932                         char buf[DECIMAL_STR_MAX(uint64_t) + 1];
933                         uint64_t val;
934
935                         if (cgroup_context_has_unified_memory_config(c)) {
936                                 val = c->memory_max;
937                                 log_cgroup_compat(u, "Applying MemoryMax %" PRIi64 " as MemoryLimit", val);
938                         } else
939                                 val = c->memory_limit;
940
941                         if (val == CGROUP_LIMIT_MAX)
942                                 strncpy(buf, "-1\n", sizeof(buf));
943                         else
944                                 xsprintf(buf, "%" PRIu64 "\n", val);
945
946                         r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf);
947                         if (r < 0)
948                                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
949                                               "Failed to set memory.limit_in_bytes: %m");
950                 }
951         }
952
953         if ((apply_mask & CGROUP_MASK_DEVICES) && !is_root) {
954                 CGroupDeviceAllow *a;
955
956                 /* Changing the devices list of a populated cgroup
957                  * might result in EINVAL, hence ignore EINVAL
958                  * here. */
959
960                 if (c->device_allow || c->device_policy != CGROUP_AUTO)
961                         r = cg_set_attribute("devices", path, "devices.deny", "a");
962                 else
963                         r = cg_set_attribute("devices", path, "devices.allow", "a");
964                 if (r < 0)
965                         log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
966                                       "Failed to reset devices.list: %m");
967
968                 if (c->device_policy == CGROUP_CLOSED ||
969                     (c->device_policy == CGROUP_AUTO && c->device_allow)) {
970                         static const char auto_devices[] =
971                                 "/dev/null\0" "rwm\0"
972                                 "/dev/zero\0" "rwm\0"
973                                 "/dev/full\0" "rwm\0"
974                                 "/dev/random\0" "rwm\0"
975                                 "/dev/urandom\0" "rwm\0"
976                                 "/dev/tty\0" "rwm\0"
977                                 "/dev/ptmx\0" "rwm\0"
978                                 /* Allow /run/systemd/inaccessible/{chr,blk} devices for mapping InaccessiblePaths */
979                                 "-/run/systemd/inaccessible/chr\0" "rwm\0"
980                                 "-/run/systemd/inaccessible/blk\0" "rwm\0";
981
982                         const char *x, *y;
983
984                         NULSTR_FOREACH_PAIR(x, y, auto_devices)
985                                 whitelist_device(path, x, y);
986
987                         /* PTS (/dev/pts) devices may not be duplicated, but accessed */
988                         whitelist_major(path, "pts", 'c', "rw");
989                 }
990
991                 LIST_FOREACH(device_allow, a, c->device_allow) {
992                         char acc[4], *val;
993                         unsigned k = 0;
994
995                         if (a->r)
996                                 acc[k++] = 'r';
997                         if (a->w)
998                                 acc[k++] = 'w';
999                         if (a->m)
1000                                 acc[k++] = 'm';
1001
1002                         if (k == 0)
1003                                 continue;
1004
1005                         acc[k++] = 0;
1006
1007                         if (path_startswith(a->path, "/dev/"))
1008                                 whitelist_device(path, a->path, acc);
1009                         else if ((val = startswith(a->path, "block-")))
1010                                 whitelist_major(path, val, 'b', acc);
1011                         else if ((val = startswith(a->path, "char-")))
1012                                 whitelist_major(path, val, 'c', acc);
1013                         else
1014                                 log_unit_debug(u, "Ignoring device %s while writing cgroup attribute.", a->path);
1015                 }
1016         }
1017
1018         if (apply_mask & CGROUP_MASK_PIDS) {
1019
1020                 if (is_root) {
1021                         /* So, the "pids" controller does not expose anything on the root cgroup, in order not to
1022                          * replicate knobs exposed elsewhere needlessly. We abstract this away here however, and when
1023                          * the knobs of the root cgroup are modified propagate this to the relevant sysctls. There's a
1024                          * non-obvious asymmetry however: unlike the cgroup properties we don't really want to take
1025                          * exclusive ownership of the sysctls, but we still want to honour things if the user sets
1026                          * limits. Hence we employ sort of a one-way strategy: when the user sets a bounded limit
1027                          * through us it counts. When the user afterwards unsets it again (i.e. sets it to unbounded)
1028                          * it also counts. But if the user never set a limit through us (i.e. we are the default of
1029                          * "unbounded") we leave things unmodified. For this we manage a global boolean that we turn on
1030                          * the first time we set a limit. Note that this boolean is flushed out on manager reload,
1031                          * which is desirable so that there's an offical way to release control of the sysctl from
1032                          * systemd: set the limit to unbounded and reload. */
1033
1034                         if (c->tasks_max != CGROUP_LIMIT_MAX) {
1035                                 u->manager->sysctl_pid_max_changed = true;
1036                                 r = procfs_tasks_set_limit(c->tasks_max);
1037                         } else if (u->manager->sysctl_pid_max_changed)
1038                                 r = procfs_tasks_set_limit(TASKS_MAX);
1039                         else
1040                                 r = 0;
1041
1042                         if (r < 0)
1043                                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
1044                                               "Failed to write to tasks limit sysctls: %m");
1045
1046                 } else {
1047                         if (c->tasks_max != CGROUP_LIMIT_MAX) {
1048                                 char buf[DECIMAL_STR_MAX(uint64_t) + 2];
1049
1050                                 sprintf(buf, "%" PRIu64 "\n", c->tasks_max);
1051                                 r = cg_set_attribute("pids", path, "pids.max", buf);
1052                         } else
1053                                 r = cg_set_attribute("pids", path, "pids.max", "max");
1054                         if (r < 0)
1055                                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
1056                                               "Failed to set pids.max: %m");
1057                 }
1058         }
1059
1060         if (apply_bpf)
1061                 cgroup_apply_firewall(u);
1062 }
1063
1064 CGroupMask cgroup_context_get_mask(CGroupContext *c) {
1065         CGroupMask mask = 0;
1066
1067         /* Figure out which controllers we need */
1068
1069         if (c->cpu_accounting ||
1070             cgroup_context_has_cpu_weight(c) ||
1071             cgroup_context_has_cpu_shares(c) ||
1072             c->cpu_quota_per_sec_usec != USEC_INFINITY)
1073                 mask |= CGROUP_MASK_CPUACCT | CGROUP_MASK_CPU;
1074
1075         if (cgroup_context_has_io_config(c) || cgroup_context_has_blockio_config(c))
1076                 mask |= CGROUP_MASK_IO | CGROUP_MASK_BLKIO;
1077
1078         if (c->memory_accounting ||
1079             c->memory_limit != CGROUP_LIMIT_MAX ||
1080             cgroup_context_has_unified_memory_config(c))
1081                 mask |= CGROUP_MASK_MEMORY;
1082
1083         if (c->device_allow ||
1084             c->device_policy != CGROUP_AUTO)
1085                 mask |= CGROUP_MASK_DEVICES;
1086
1087         if (c->tasks_accounting ||
1088             c->tasks_max != CGROUP_LIMIT_MAX)
1089                 mask |= CGROUP_MASK_PIDS;
1090
1091         return mask;
1092 }
1093
1094 CGroupMask unit_get_own_mask(Unit *u) {
1095         CGroupContext *c;
1096
1097         /* Returns the mask of controllers the unit needs for itself */
1098
1099         c = unit_get_cgroup_context(u);
1100         if (!c)
1101                 return 0;
1102
1103         return cgroup_context_get_mask(c) | unit_get_delegate_mask(u);
1104 }
1105
1106 CGroupMask unit_get_delegate_mask(Unit *u) {
1107         CGroupContext *c;
1108
1109         /* If delegation is turned on, then turn on selected controllers, unless we are on the legacy hierarchy and the
1110          * process we fork into is known to drop privileges, and hence shouldn't get access to the controllers.
1111          *
1112          * Note that on the unified hierarchy it is safe to delegate controllers to unprivileged services. */
1113
1114         if (!unit_cgroup_delegate(u))
1115                 return 0;
1116
1117         if (cg_all_unified() <= 0) {
1118                 ExecContext *e;
1119
1120                 e = unit_get_exec_context(u);
1121                 if (e && !exec_context_maintains_privileges(e))
1122                         return 0;
1123         }
1124
1125         assert_se(c = unit_get_cgroup_context(u));
1126         return c->delegate_controllers;
1127 }
1128
1129 CGroupMask unit_get_members_mask(Unit *u) {
1130         assert(u);
1131
1132         /* Returns the mask of controllers all of the unit's children require, merged */
1133
1134         if (u->cgroup_members_mask_valid)
1135                 return u->cgroup_members_mask;
1136
1137         u->cgroup_members_mask = 0;
1138
1139         if (u->type == UNIT_SLICE) {
1140                 void *v;
1141                 Unit *member;
1142                 Iterator i;
1143
1144                 HASHMAP_FOREACH_KEY(v, member, u->dependencies[UNIT_BEFORE], i) {
1145
1146                         if (member == u)
1147                                 continue;
1148
1149                         if (UNIT_DEREF(member->slice) != u)
1150                                 continue;
1151
1152                         u->cgroup_members_mask |= unit_get_subtree_mask(member); /* note that this calls ourselves again, for the children */
1153                 }
1154         }
1155
1156         u->cgroup_members_mask_valid = true;
1157         return u->cgroup_members_mask;
1158 }
1159
1160 CGroupMask unit_get_siblings_mask(Unit *u) {
1161         assert(u);
1162
1163         /* Returns the mask of controllers all of the unit's siblings
1164          * require, i.e. the members mask of the unit's parent slice
1165          * if there is one. */
1166
1167         if (UNIT_ISSET(u->slice))
1168                 return unit_get_members_mask(UNIT_DEREF(u->slice));
1169
1170         return unit_get_subtree_mask(u); /* we are the top-level slice */
1171 }
1172
1173 CGroupMask unit_get_subtree_mask(Unit *u) {
1174
1175         /* Returns the mask of this subtree, meaning of the group
1176          * itself and its children. */
1177
1178         return unit_get_own_mask(u) | unit_get_members_mask(u);
1179 }
1180
1181 CGroupMask unit_get_target_mask(Unit *u) {
1182         CGroupMask mask;
1183
1184         /* This returns the cgroup mask of all controllers to enable
1185          * for a specific cgroup, i.e. everything it needs itself,
1186          * plus all that its children need, plus all that its siblings
1187          * need. This is primarily useful on the legacy cgroup
1188          * hierarchy, where we need to duplicate each cgroup in each
1189          * hierarchy that shall be enabled for it. */
1190
1191         mask = unit_get_own_mask(u) | unit_get_members_mask(u) | unit_get_siblings_mask(u);
1192         mask &= u->manager->cgroup_supported;
1193
1194         return mask;
1195 }
1196
1197 CGroupMask unit_get_enable_mask(Unit *u) {
1198         CGroupMask mask;
1199
1200         /* This returns the cgroup mask of all controllers to enable
1201          * for the children of a specific cgroup. This is primarily
1202          * useful for the unified cgroup hierarchy, where each cgroup
1203          * controls which controllers are enabled for its children. */
1204
1205         mask = unit_get_members_mask(u);
1206         mask &= u->manager->cgroup_supported;
1207
1208         return mask;
1209 }
1210
1211 bool unit_get_needs_bpf(Unit *u) {
1212         CGroupContext *c;
1213         Unit *p;
1214         assert(u);
1215
1216         c = unit_get_cgroup_context(u);
1217         if (!c)
1218                 return false;
1219
1220         if (c->ip_accounting ||
1221             c->ip_address_allow ||
1222             c->ip_address_deny)
1223                 return true;
1224
1225         /* If any parent slice has an IP access list defined, it applies too */
1226         for (p = UNIT_DEREF(u->slice); p; p = UNIT_DEREF(p->slice)) {
1227                 c = unit_get_cgroup_context(p);
1228                 if (!c)
1229                         return false;
1230
1231                 if (c->ip_address_allow ||
1232                     c->ip_address_deny)
1233                         return true;
1234         }
1235
1236         return false;
1237 }
1238
1239 /* Recurse from a unit up through its containing slices, propagating
1240  * mask bits upward. A unit is also member of itself. */
1241 void unit_update_cgroup_members_masks(Unit *u) {
1242         CGroupMask m;
1243         bool more;
1244
1245         assert(u);
1246
1247         /* Calculate subtree mask */
1248         m = unit_get_subtree_mask(u);
1249
1250         /* See if anything changed from the previous invocation. If
1251          * not, we're done. */
1252         if (u->cgroup_subtree_mask_valid && m == u->cgroup_subtree_mask)
1253                 return;
1254
1255         more =
1256                 u->cgroup_subtree_mask_valid &&
1257                 ((m & ~u->cgroup_subtree_mask) != 0) &&
1258                 ((~m & u->cgroup_subtree_mask) == 0);
1259
1260         u->cgroup_subtree_mask = m;
1261         u->cgroup_subtree_mask_valid = true;
1262
1263         if (UNIT_ISSET(u->slice)) {
1264                 Unit *s = UNIT_DEREF(u->slice);
1265
1266                 if (more)
1267                         /* There's more set now than before. We
1268                          * propagate the new mask to the parent's mask
1269                          * (not caring if it actually was valid or
1270                          * not). */
1271
1272                         s->cgroup_members_mask |= m;
1273
1274                 else
1275                         /* There's less set now than before (or we
1276                          * don't know), we need to recalculate
1277                          * everything, so let's invalidate the
1278                          * parent's members mask */
1279
1280                         s->cgroup_members_mask_valid = false;
1281
1282                 /* And now make sure that this change also hits our
1283                  * grandparents */
1284                 unit_update_cgroup_members_masks(s);
1285         }
1286 }
1287
1288 const char *unit_get_realized_cgroup_path(Unit *u, CGroupMask mask) {
1289
1290         /* Returns the realized cgroup path of the specified unit where all specified controllers are available. */
1291
1292         while (u) {
1293
1294                 if (u->cgroup_path &&
1295                     u->cgroup_realized &&
1296                     FLAGS_SET(u->cgroup_realized_mask, mask))
1297                         return u->cgroup_path;
1298
1299                 u = UNIT_DEREF(u->slice);
1300         }
1301
1302         return NULL;
1303 }
1304
1305 static const char *migrate_callback(CGroupMask mask, void *userdata) {
1306         return unit_get_realized_cgroup_path(userdata, mask);
1307 }
1308
1309 char *unit_default_cgroup_path(Unit *u) {
1310         _cleanup_free_ char *escaped = NULL, *slice = NULL;
1311         int r;
1312
1313         assert(u);
1314
1315         if (unit_has_name(u, SPECIAL_ROOT_SLICE))
1316                 return strdup(u->manager->cgroup_root);
1317
1318         if (UNIT_ISSET(u->slice) && !unit_has_name(UNIT_DEREF(u->slice), SPECIAL_ROOT_SLICE)) {
1319                 r = cg_slice_to_path(UNIT_DEREF(u->slice)->id, &slice);
1320                 if (r < 0)
1321                         return NULL;
1322         }
1323
1324         escaped = cg_escape(u->id);
1325         if (!escaped)
1326                 return NULL;
1327
1328         if (slice)
1329                 return strjoin(u->manager->cgroup_root, "/", slice, "/",
1330                                escaped);
1331         else
1332                 return strjoin(u->manager->cgroup_root, "/", escaped);
1333 }
1334
1335 int unit_set_cgroup_path(Unit *u, const char *path) {
1336         _cleanup_free_ char *p = NULL;
1337         int r;
1338
1339         assert(u);
1340
1341         if (path) {
1342                 p = strdup(path);
1343                 if (!p)
1344                         return -ENOMEM;
1345         } else
1346                 p = NULL;
1347
1348         if (streq_ptr(u->cgroup_path, p))
1349                 return 0;
1350
1351         if (p) {
1352                 r = hashmap_put(u->manager->cgroup_unit, p, u);
1353                 if (r < 0)
1354                         return r;
1355         }
1356
1357         unit_release_cgroup(u);
1358
1359         u->cgroup_path = TAKE_PTR(p);
1360
1361         return 1;
1362 }
1363
1364 int unit_watch_cgroup(Unit *u) {
1365         _cleanup_free_ char *events = NULL;
1366         int r;
1367
1368         assert(u);
1369
1370         if (!u->cgroup_path)
1371                 return 0;
1372
1373         if (u->cgroup_inotify_wd >= 0)
1374                 return 0;
1375
1376         /* Only applies to the unified hierarchy */
1377         r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
1378         if (r < 0)
1379                 return log_error_errno(r, "Failed to determine whether the name=systemd hierarchy is unified: %m");
1380         if (r == 0)
1381                 return 0;
1382
1383         /* Don't watch the root slice, it's pointless. */
1384         if (unit_has_name(u, SPECIAL_ROOT_SLICE))
1385                 return 0;
1386
1387         r = hashmap_ensure_allocated(&u->manager->cgroup_inotify_wd_unit, &trivial_hash_ops);
1388         if (r < 0)
1389                 return log_oom();
1390
1391         r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "cgroup.events", &events);
1392         if (r < 0)
1393                 return log_oom();
1394
1395         u->cgroup_inotify_wd = inotify_add_watch(u->manager->cgroup_inotify_fd, events, IN_MODIFY);
1396         if (u->cgroup_inotify_wd < 0) {
1397
1398                 if (errno == ENOENT) /* If the directory is already
1399                                       * gone we don't need to track
1400                                       * it, so this is not an error */
1401                         return 0;
1402
1403                 return log_unit_error_errno(u, errno, "Failed to add inotify watch descriptor for control group %s: %m", u->cgroup_path);
1404         }
1405
1406         r = hashmap_put(u->manager->cgroup_inotify_wd_unit, INT_TO_PTR(u->cgroup_inotify_wd), u);
1407         if (r < 0)
1408                 return log_unit_error_errno(u, r, "Failed to add inotify watch descriptor to hash map: %m");
1409
1410         return 0;
1411 }
1412
1413 int unit_pick_cgroup_path(Unit *u) {
1414         _cleanup_free_ char *path = NULL;
1415         int r;
1416
1417         assert(u);
1418
1419         if (u->cgroup_path)
1420                 return 0;
1421
1422         if (!UNIT_HAS_CGROUP_CONTEXT(u))
1423                 return -EINVAL;
1424
1425         path = unit_default_cgroup_path(u);
1426         if (!path)
1427                 return log_oom();
1428
1429         r = unit_set_cgroup_path(u, path);
1430         if (r == -EEXIST)
1431                 return log_unit_error_errno(u, r, "Control group %s exists already.", path);
1432         if (r < 0)
1433                 return log_unit_error_errno(u, r, "Failed to set unit's control group path to %s: %m", path);
1434
1435         return 0;
1436 }
1437
1438 static int unit_create_cgroup(
1439                 Unit *u,
1440                 CGroupMask target_mask,
1441                 CGroupMask enable_mask,
1442                 bool needs_bpf) {
1443
1444         CGroupContext *c;
1445         int r;
1446         bool created;
1447
1448         assert(u);
1449
1450         c = unit_get_cgroup_context(u);
1451         if (!c)
1452                 return 0;
1453
1454         /* Figure out our cgroup path */
1455         r = unit_pick_cgroup_path(u);
1456         if (r < 0)
1457                 return r;
1458
1459         /* First, create our own group */
1460         r = cg_create_everywhere(u->manager->cgroup_supported, target_mask, u->cgroup_path);
1461         if (r < 0)
1462                 return log_unit_error_errno(u, r, "Failed to create cgroup %s: %m", u->cgroup_path);
1463         created = !!r;
1464
1465         /* Start watching it */
1466         (void) unit_watch_cgroup(u);
1467
1468         /* Preserve enabled controllers in delegated units, adjust others. */
1469         if (created || !unit_cgroup_delegate(u)) {
1470
1471                 /* Enable all controllers we need */
1472                 r = cg_enable_everywhere(u->manager->cgroup_supported, enable_mask, u->cgroup_path);
1473                 if (r < 0)
1474                         log_unit_warning_errno(u, r, "Failed to enable controllers on cgroup %s, ignoring: %m",
1475                                                u->cgroup_path);
1476         }
1477
1478         /* Keep track that this is now realized */
1479         u->cgroup_realized = true;
1480         u->cgroup_realized_mask = target_mask;
1481         u->cgroup_enabled_mask = enable_mask;
1482         u->cgroup_bpf_state = needs_bpf ? UNIT_CGROUP_BPF_ON : UNIT_CGROUP_BPF_OFF;
1483
1484         if (u->type != UNIT_SLICE && !unit_cgroup_delegate(u)) {
1485
1486                 /* Then, possibly move things over, but not if
1487                  * subgroups may contain processes, which is the case
1488                  * for slice and delegation units. */
1489                 r = cg_migrate_everywhere(u->manager->cgroup_supported, u->cgroup_path, u->cgroup_path, migrate_callback, u);
1490                 if (r < 0)
1491                         log_unit_warning_errno(u, r, "Failed to migrate cgroup from to %s, ignoring: %m", u->cgroup_path);
1492         }
1493
1494         return 0;
1495 }
1496
1497 static int unit_attach_pid_to_cgroup_via_bus(Unit *u, pid_t pid, const char *suffix_path) {
1498         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1499         char *pp;
1500         int r;
1501
1502         assert(u);
1503
1504         if (MANAGER_IS_SYSTEM(u->manager))
1505                 return -EINVAL;
1506
1507         if (!u->manager->system_bus)
1508                 return -EIO;
1509
1510         if (!u->cgroup_path)
1511                 return -EINVAL;
1512
1513         /* Determine this unit's cgroup path relative to our cgroup root */
1514         pp = path_startswith(u->cgroup_path, u->manager->cgroup_root);
1515         if (!pp)
1516                 return -EINVAL;
1517
1518         pp = strjoina("/", pp, suffix_path);
1519         path_simplify(pp, false);
1520
1521         r = sd_bus_call_method(u->manager->system_bus,
1522                                "org.freedesktop.systemd1",
1523                                "/org/freedesktop/systemd1",
1524                                "org.freedesktop.systemd1.Manager",
1525                                "AttachProcessesToUnit",
1526                                &error, NULL,
1527                                "ssau",
1528                                NULL /* empty unit name means client's unit, i.e. us */, pp, 1, (uint32_t) pid);
1529         if (r < 0)
1530                 return log_unit_debug_errno(u, r, "Failed to attach unit process " PID_FMT " via the bus: %s", pid, bus_error_message(&error, r));
1531
1532         return 0;
1533 }
1534
1535 int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const char *suffix_path) {
1536         CGroupMask delegated_mask;
1537         const char *p;
1538         Iterator i;
1539         void *pidp;
1540         int r, q;
1541
1542         assert(u);
1543
1544         if (!UNIT_HAS_CGROUP_CONTEXT(u))
1545                 return -EINVAL;
1546
1547         if (set_isempty(pids))
1548                 return 0;
1549
1550         r = unit_realize_cgroup(u);
1551         if (r < 0)
1552                 return r;
1553
1554         if (isempty(suffix_path))
1555                 p = u->cgroup_path;
1556         else
1557                 p = strjoina(u->cgroup_path, "/", suffix_path);
1558
1559         delegated_mask = unit_get_delegate_mask(u);
1560
1561         r = 0;
1562         SET_FOREACH(pidp, pids, i) {
1563                 pid_t pid = PTR_TO_PID(pidp);
1564                 CGroupController c;
1565
1566                 /* First, attach the PID to the main cgroup hierarchy */
1567                 q = cg_attach(SYSTEMD_CGROUP_CONTROLLER, p, pid);
1568                 if (q < 0) {
1569                         log_unit_debug_errno(u, q, "Couldn't move process " PID_FMT " to requested cgroup '%s': %m", pid, p);
1570
1571                         if (MANAGER_IS_USER(u->manager) && IN_SET(q, -EPERM, -EACCES)) {
1572                                 int z;
1573
1574                                 /* If we are in a user instance, and we can't move the process ourselves due to
1575                                  * permission problems, let's ask the system instance about it instead. Since it's more
1576                                  * privileged it might be able to move the process across the leaves of a subtree who's
1577                                  * top node is not owned by us. */
1578
1579                                 z = unit_attach_pid_to_cgroup_via_bus(u, pid, suffix_path);
1580                                 if (z < 0)
1581                                         log_unit_debug_errno(u, z, "Couldn't move process " PID_FMT " to requested cgroup '%s' via the system bus either: %m", pid, p);
1582                                 else
1583                                         continue; /* When the bus thing worked via the bus we are fully done for this PID. */
1584                         }
1585
1586                         if (r >= 0)
1587                                 r = q; /* Remember first error */
1588
1589                         continue;
1590                 }
1591
1592                 q = cg_all_unified();
1593                 if (q < 0)
1594                         return q;
1595                 if (q > 0)
1596                         continue;
1597
1598                 /* In the legacy hierarchy, attach the process to the request cgroup if possible, and if not to the
1599                  * innermost realized one */
1600
1601                 for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
1602                         CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c);
1603                         const char *realized;
1604
1605                         if (!(u->manager->cgroup_supported & bit))
1606                                 continue;
1607
1608                         /* If this controller is delegated and realized, honour the caller's request for the cgroup suffix. */
1609                         if (delegated_mask & u->cgroup_realized_mask & bit) {
1610                                 q = cg_attach(cgroup_controller_to_string(c), p, pid);
1611                                 if (q >= 0)
1612                                         continue; /* Success! */
1613
1614                                 log_unit_debug_errno(u, q, "Failed to attach PID " PID_FMT " to requested cgroup %s in controller %s, falling back to unit's cgroup: %m",
1615                                                      pid, p, cgroup_controller_to_string(c));
1616                         }
1617
1618                         /* So this controller is either not delegate or realized, or something else weird happened. In
1619                          * that case let's attach the PID at least to the closest cgroup up the tree that is
1620                          * realized. */
1621                         realized = unit_get_realized_cgroup_path(u, bit);
1622                         if (!realized)
1623                                 continue; /* Not even realized in the root slice? Then let's not bother */
1624
1625                         q = cg_attach(cgroup_controller_to_string(c), realized, pid);
1626                         if (q < 0)
1627                                 log_unit_debug_errno(u, q, "Failed to attach PID " PID_FMT " to realized cgroup %s in controller %s, ignoring: %m",
1628                                                      pid, realized, cgroup_controller_to_string(c));
1629                 }
1630         }
1631
1632         return r;
1633 }
1634
1635 static void cgroup_xattr_apply(Unit *u) {
1636         char ids[SD_ID128_STRING_MAX];
1637         int r;
1638
1639         assert(u);
1640
1641         if (!MANAGER_IS_SYSTEM(u->manager))
1642                 return;
1643
1644         if (sd_id128_is_null(u->invocation_id))
1645                 return;
1646
1647         r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path,
1648                          "trusted.invocation_id",
1649                          sd_id128_to_string(u->invocation_id, ids), 32,
1650                          0);
1651         if (r < 0)
1652                 log_unit_debug_errno(u, r, "Failed to set invocation ID on control group %s, ignoring: %m", u->cgroup_path);
1653 }
1654
1655 static bool unit_has_mask_realized(
1656                 Unit *u,
1657                 CGroupMask target_mask,
1658                 CGroupMask enable_mask,
1659                 bool needs_bpf) {
1660
1661         assert(u);
1662
1663         return u->cgroup_realized &&
1664                 u->cgroup_realized_mask == target_mask &&
1665                 u->cgroup_enabled_mask == enable_mask &&
1666                 ((needs_bpf && u->cgroup_bpf_state == UNIT_CGROUP_BPF_ON) ||
1667                  (!needs_bpf && u->cgroup_bpf_state == UNIT_CGROUP_BPF_OFF));
1668 }
1669
1670 static void unit_add_to_cgroup_realize_queue(Unit *u) {
1671         assert(u);
1672
1673         if (u->in_cgroup_realize_queue)
1674                 return;
1675
1676         LIST_PREPEND(cgroup_realize_queue, u->manager->cgroup_realize_queue, u);
1677         u->in_cgroup_realize_queue = true;
1678 }
1679
1680 static void unit_remove_from_cgroup_realize_queue(Unit *u) {
1681         assert(u);
1682
1683         if (!u->in_cgroup_realize_queue)
1684                 return;
1685
1686         LIST_REMOVE(cgroup_realize_queue, u->manager->cgroup_realize_queue, u);
1687         u->in_cgroup_realize_queue = false;
1688 }
1689
1690 /* Check if necessary controllers and attributes for a unit are in place.
1691  *
1692  * If so, do nothing.
1693  * If not, create paths, move processes over, and set attributes.
1694  *
1695  * Returns 0 on success and < 0 on failure. */
1696 static int unit_realize_cgroup_now(Unit *u, ManagerState state) {
1697         CGroupMask target_mask, enable_mask;
1698         bool needs_bpf, apply_bpf;
1699         int r;
1700
1701         assert(u);
1702
1703         unit_remove_from_cgroup_realize_queue(u);
1704
1705         target_mask = unit_get_target_mask(u);
1706         enable_mask = unit_get_enable_mask(u);
1707         needs_bpf = unit_get_needs_bpf(u);
1708
1709         if (unit_has_mask_realized(u, target_mask, enable_mask, needs_bpf))
1710                 return 0;
1711
1712         /* Make sure we apply the BPF filters either when one is configured, or if none is configured but previously
1713          * the state was anything but off. This way, if a unit with a BPF filter applied is reconfigured to lose it
1714          * this will trickle down properly to cgroupfs. */
1715         apply_bpf = needs_bpf || u->cgroup_bpf_state != UNIT_CGROUP_BPF_OFF;
1716
1717         /* First, realize parents */
1718         if (UNIT_ISSET(u->slice)) {
1719                 r = unit_realize_cgroup_now(UNIT_DEREF(u->slice), state);
1720                 if (r < 0)
1721                         return r;
1722         }
1723
1724         /* And then do the real work */
1725         r = unit_create_cgroup(u, target_mask, enable_mask, needs_bpf);
1726         if (r < 0)
1727                 return r;
1728
1729         /* Finally, apply the necessary attributes. */
1730         cgroup_context_apply(u, target_mask, apply_bpf, state);
1731         cgroup_xattr_apply(u);
1732
1733         return 0;
1734 }
1735
1736 unsigned manager_dispatch_cgroup_realize_queue(Manager *m) {
1737         ManagerState state;
1738         unsigned n = 0;
1739         Unit *i;
1740         int r;
1741
1742         assert(m);
1743
1744         state = manager_state(m);
1745
1746         while ((i = m->cgroup_realize_queue)) {
1747                 assert(i->in_cgroup_realize_queue);
1748
1749                 if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(i))) {
1750                         /* Maybe things changed, and the unit is not actually active anymore? */
1751                         unit_remove_from_cgroup_realize_queue(i);
1752                         continue;
1753                 }
1754
1755                 r = unit_realize_cgroup_now(i, state);
1756                 if (r < 0)
1757                         log_warning_errno(r, "Failed to realize cgroups for queued unit %s, ignoring: %m", i->id);
1758
1759                 n++;
1760         }
1761
1762         return n;
1763 }
1764
1765 static void unit_add_siblings_to_cgroup_realize_queue(Unit *u) {
1766         Unit *slice;
1767
1768         /* This adds the siblings of the specified unit and the
1769          * siblings of all parent units to the cgroup queue. (But
1770          * neither the specified unit itself nor the parents.) */
1771
1772         while ((slice = UNIT_DEREF(u->slice))) {
1773                 Iterator i;
1774                 Unit *m;
1775                 void *v;
1776
1777                 HASHMAP_FOREACH_KEY(v, m, u->dependencies[UNIT_BEFORE], i) {
1778                         if (m == u)
1779                                 continue;
1780
1781                         /* Skip units that have a dependency on the slice
1782                          * but aren't actually in it. */
1783                         if (UNIT_DEREF(m->slice) != slice)
1784                                 continue;
1785
1786                         /* No point in doing cgroup application for units
1787                          * without active processes. */
1788                         if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(m)))
1789                                 continue;
1790
1791                         /* If the unit doesn't need any new controllers
1792                          * and has current ones realized, it doesn't need
1793                          * any changes. */
1794                         if (unit_has_mask_realized(m,
1795                                                    unit_get_target_mask(m),
1796                                                    unit_get_enable_mask(m),
1797                                                    unit_get_needs_bpf(m)))
1798                                 continue;
1799
1800                         unit_add_to_cgroup_realize_queue(m);
1801                 }
1802
1803                 u = slice;
1804         }
1805 }
1806
1807 int unit_realize_cgroup(Unit *u) {
1808         assert(u);
1809
1810         if (!UNIT_HAS_CGROUP_CONTEXT(u))
1811                 return 0;
1812
1813         /* So, here's the deal: when realizing the cgroups for this
1814          * unit, we need to first create all parents, but there's more
1815          * actually: for the weight-based controllers we also need to
1816          * make sure that all our siblings (i.e. units that are in the
1817          * same slice as we are) have cgroups, too. Otherwise, things
1818          * would become very uneven as each of their processes would
1819          * get as much resources as all our group together. This call
1820          * will synchronously create the parent cgroups, but will
1821          * defer work on the siblings to the next event loop
1822          * iteration. */
1823
1824         /* Add all sibling slices to the cgroup queue. */
1825         unit_add_siblings_to_cgroup_realize_queue(u);
1826
1827         /* And realize this one now (and apply the values) */
1828         return unit_realize_cgroup_now(u, manager_state(u->manager));
1829 }
1830
1831 void unit_release_cgroup(Unit *u) {
1832         assert(u);
1833
1834         /* Forgets all cgroup details for this cgroup */
1835
1836         if (u->cgroup_path) {
1837                 (void) hashmap_remove(u->manager->cgroup_unit, u->cgroup_path);
1838                 u->cgroup_path = mfree(u->cgroup_path);
1839         }
1840
1841         if (u->cgroup_inotify_wd >= 0) {
1842                 if (inotify_rm_watch(u->manager->cgroup_inotify_fd, u->cgroup_inotify_wd) < 0)
1843                         log_unit_debug_errno(u, errno, "Failed to remove cgroup inotify watch %i for %s, ignoring", u->cgroup_inotify_wd, u->id);
1844
1845                 (void) hashmap_remove(u->manager->cgroup_inotify_wd_unit, INT_TO_PTR(u->cgroup_inotify_wd));
1846                 u->cgroup_inotify_wd = -1;
1847         }
1848 }
1849
1850 void unit_prune_cgroup(Unit *u) {
1851         int r;
1852         bool is_root_slice;
1853
1854         assert(u);
1855
1856         /* Removes the cgroup, if empty and possible, and stops watching it. */
1857
1858         if (!u->cgroup_path)
1859                 return;
1860
1861         (void) unit_get_cpu_usage(u, NULL); /* Cache the last CPU usage value before we destroy the cgroup */
1862
1863         is_root_slice = unit_has_name(u, SPECIAL_ROOT_SLICE);
1864
1865         r = cg_trim_everywhere(u->manager->cgroup_supported, u->cgroup_path, !is_root_slice);
1866         if (r < 0) {
1867                 log_unit_debug_errno(u, r, "Failed to destroy cgroup %s, ignoring: %m", u->cgroup_path);
1868                 return;
1869         }
1870
1871         if (is_root_slice)
1872                 return;
1873
1874         unit_release_cgroup(u);
1875
1876         u->cgroup_realized = false;
1877         u->cgroup_realized_mask = 0;
1878         u->cgroup_enabled_mask = 0;
1879 }
1880
1881 int unit_search_main_pid(Unit *u, pid_t *ret) {
1882         _cleanup_fclose_ FILE *f = NULL;
1883         pid_t pid = 0, npid, mypid;
1884         int r;
1885
1886         assert(u);
1887         assert(ret);
1888
1889         if (!u->cgroup_path)
1890                 return -ENXIO;
1891
1892         r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &f);
1893         if (r < 0)
1894                 return r;
1895
1896         mypid = getpid_cached();
1897         while (cg_read_pid(f, &npid) > 0)  {
1898                 pid_t ppid;
1899
1900                 if (npid == pid)
1901                         continue;
1902
1903                 /* Ignore processes that aren't our kids */
1904                 if (get_process_ppid(npid, &ppid) >= 0 && ppid != mypid)
1905                         continue;
1906
1907                 if (pid != 0)
1908                         /* Dang, there's more than one daemonized PID
1909                         in this group, so we don't know what process
1910                         is the main process. */
1911
1912                         return -ENODATA;
1913
1914                 pid = npid;
1915         }
1916
1917         *ret = pid;
1918         return 0;
1919 }
1920
1921 static int unit_watch_pids_in_path(Unit *u, const char *path) {
1922         _cleanup_closedir_ DIR *d = NULL;
1923         _cleanup_fclose_ FILE *f = NULL;
1924         int ret = 0, r;
1925
1926         assert(u);
1927         assert(path);
1928
1929         r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, path, &f);
1930         if (r < 0)
1931                 ret = r;
1932         else {
1933                 pid_t pid;
1934
1935                 while ((r = cg_read_pid(f, &pid)) > 0) {
1936                         r = unit_watch_pid(u, pid);
1937                         if (r < 0 && ret >= 0)
1938                                 ret = r;
1939                 }
1940
1941                 if (r < 0 && ret >= 0)
1942                         ret = r;
1943         }
1944
1945         r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, path, &d);
1946         if (r < 0) {
1947                 if (ret >= 0)
1948                         ret = r;
1949         } else {
1950                 char *fn;
1951
1952                 while ((r = cg_read_subgroup(d, &fn)) > 0) {
1953                         _cleanup_free_ char *p = NULL;
1954
1955                         p = strjoin(path, "/", fn);
1956                         free(fn);
1957
1958                         if (!p)
1959                                 return -ENOMEM;
1960
1961                         r = unit_watch_pids_in_path(u, p);
1962                         if (r < 0 && ret >= 0)
1963                                 ret = r;
1964                 }
1965
1966                 if (r < 0 && ret >= 0)
1967                         ret = r;
1968         }
1969
1970         return ret;
1971 }
1972
1973 int unit_synthesize_cgroup_empty_event(Unit *u) {
1974         int r;
1975
1976         assert(u);
1977
1978         /* Enqueue a synthetic cgroup empty event if this unit doesn't watch any PIDs anymore. This is compatibility
1979          * support for non-unified systems where notifications aren't reliable, and hence need to take whatever we can
1980          * get as notification source as soon as we stopped having any useful PIDs to watch for. */
1981
1982         if (!u->cgroup_path)
1983                 return -ENOENT;
1984
1985         r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
1986         if (r < 0)
1987                 return r;
1988         if (r > 0) /* On unified we have reliable notifications, and don't need this */
1989                 return 0;
1990
1991         if (!set_isempty(u->pids))
1992                 return 0;
1993
1994         unit_add_to_cgroup_empty_queue(u);
1995         return 0;
1996 }
1997
1998 int unit_watch_all_pids(Unit *u) {
1999         int r;
2000
2001         assert(u);
2002
2003         /* Adds all PIDs from our cgroup to the set of PIDs we
2004          * watch. This is a fallback logic for cases where we do not
2005          * get reliable cgroup empty notifications: we try to use
2006          * SIGCHLD as replacement. */
2007
2008         if (!u->cgroup_path)
2009                 return -ENOENT;
2010
2011         r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
2012         if (r < 0)
2013                 return r;
2014         if (r > 0) /* On unified we can use proper notifications */
2015                 return 0;
2016
2017         return unit_watch_pids_in_path(u, u->cgroup_path);
2018 }
2019
2020 static int on_cgroup_empty_event(sd_event_source *s, void *userdata) {
2021         Manager *m = userdata;
2022         Unit *u;
2023         int r;
2024
2025         assert(s);
2026         assert(m);
2027
2028         u = m->cgroup_empty_queue;
2029         if (!u)
2030                 return 0;
2031
2032         assert(u->in_cgroup_empty_queue);
2033         u->in_cgroup_empty_queue = false;
2034         LIST_REMOVE(cgroup_empty_queue, m->cgroup_empty_queue, u);
2035
2036         if (m->cgroup_empty_queue) {
2037                 /* More stuff queued, let's make sure we remain enabled */
2038                 r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT);
2039                 if (r < 0)
2040                         log_debug_errno(r, "Failed to reenable cgroup empty event source, ignoring: %m");
2041         }
2042
2043         unit_add_to_gc_queue(u);
2044
2045         if (UNIT_VTABLE(u)->notify_cgroup_empty)
2046                 UNIT_VTABLE(u)->notify_cgroup_empty(u);
2047
2048         return 0;
2049 }
2050
2051 void unit_add_to_cgroup_empty_queue(Unit *u) {
2052         int r;
2053
2054         assert(u);
2055
2056         /* Note that there are four different ways how cgroup empty events reach us:
2057          *
2058          * 1. On the unified hierarchy we get an inotify event on the cgroup
2059          *
2060          * 2. On the legacy hierarchy, when running in system mode, we get a datagram on the cgroup agent socket
2061          *
2062          * 3. On the legacy hierarchy, when running in user mode, we get a D-Bus signal on the system bus
2063          *
2064          * 4. On the legacy hierarchy, in service units we start watching all processes of the cgroup for SIGCHLD as
2065          *    soon as we get one SIGCHLD, to deal with unreliable cgroup notifications.
2066          *
2067          * Regardless which way we got the notification, we'll verify it here, and then add it to a separate
2068          * queue. This queue will be dispatched at a lower priority than the SIGCHLD handler, so that we always use
2069          * SIGCHLD if we can get it first, and only use the cgroup empty notifications if there's no SIGCHLD pending
2070          * (which might happen if the cgroup doesn't contain processes that are our own child, which is typically the
2071          * case for scope units). */
2072
2073         if (u->in_cgroup_empty_queue)
2074                 return;
2075
2076         /* Let's verify that the cgroup is really empty */
2077         if (!u->cgroup_path)
2078                 return;
2079         r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path);
2080         if (r < 0) {
2081                 log_unit_debug_errno(u, r, "Failed to determine whether cgroup %s is empty: %m", u->cgroup_path);
2082                 return;
2083         }
2084         if (r == 0)
2085                 return;
2086
2087         LIST_PREPEND(cgroup_empty_queue, u->manager->cgroup_empty_queue, u);
2088         u->in_cgroup_empty_queue = true;
2089
2090         /* Trigger the defer event */
2091         r = sd_event_source_set_enabled(u->manager->cgroup_empty_event_source, SD_EVENT_ONESHOT);
2092         if (r < 0)
2093                 log_debug_errno(r, "Failed to enable cgroup empty event source: %m");
2094 }
2095
2096 static int on_cgroup_inotify_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
2097         Manager *m = userdata;
2098
2099         assert(s);
2100         assert(fd >= 0);
2101         assert(m);
2102
2103         for (;;) {
2104                 union inotify_event_buffer buffer;
2105                 struct inotify_event *e;
2106                 ssize_t l;
2107
2108                 l = read(fd, &buffer, sizeof(buffer));
2109                 if (l < 0) {
2110                         if (IN_SET(errno, EINTR, EAGAIN))
2111                                 return 0;
2112
2113                         return log_error_errno(errno, "Failed to read control group inotify events: %m");
2114                 }
2115
2116                 FOREACH_INOTIFY_EVENT(e, buffer, l) {
2117                         Unit *u;
2118
2119                         if (e->wd < 0)
2120                                 /* Queue overflow has no watch descriptor */
2121                                 continue;
2122
2123                         if (e->mask & IN_IGNORED)
2124                                 /* The watch was just removed */
2125                                 continue;
2126
2127                         u = hashmap_get(m->cgroup_inotify_wd_unit, INT_TO_PTR(e->wd));
2128                         if (!u) /* Not that inotify might deliver
2129                                  * events for a watch even after it
2130                                  * was removed, because it was queued
2131                                  * before the removal. Let's ignore
2132                                  * this here safely. */
2133                                 continue;
2134
2135                         unit_add_to_cgroup_empty_queue(u);
2136                 }
2137         }
2138 }
2139 #endif // 0
2140
2141 int manager_setup_cgroup(Manager *m) {
2142         _cleanup_free_ char *path = NULL;
2143         const char *scope_path;
2144         CGroupController c;
2145         int r, all_unified;
2146 #if 0 /// UNNEEDED by elogind
2147         char *e;
2148 #endif // 0
2149
2150         assert(m);
2151
2152         /* 1. Determine hierarchy */
2153         m->cgroup_root = mfree(m->cgroup_root);
2154 #if 0 /// elogind is not init and must therefore search for PID 1 instead of self.
2155         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &m->cgroup_root);
2156 #else
2157         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &m->cgroup_root);
2158 #endif // 0
2159         if (r < 0)
2160                 return log_error_errno(r, "Cannot determine cgroup we are running in: %m");
2161
2162 #if 0 /// elogind does not support systemd scopes and slices
2163         /* Chop off the init scope, if we are already located in it */
2164         e = endswith(m->cgroup_root, "/" SPECIAL_INIT_SCOPE);
2165
2166         /* LEGACY: Also chop off the system slice if we are in
2167          * it. This is to support live upgrades from older systemd
2168          * versions where PID 1 was moved there. Also see
2169          * cg_get_root_path(). */
2170         if (!e && MANAGER_IS_SYSTEM(m)) {
2171                 e = endswith(m->cgroup_root, "/" SPECIAL_SYSTEM_SLICE);
2172                 if (!e)
2173                         e = endswith(m->cgroup_root, "/system"); /* even more legacy */
2174         }
2175         if (e)
2176                 *e = 0;
2177 #endif // 0
2178
2179         log_debug_elogind("Cgroup Controller \"%s\" -> root \"%s\"",
2180                           SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root);
2181         /* And make sure to store away the root value without trailing slash, even for the root dir, so that we can
2182          * easily prepend it everywhere. */
2183         delete_trailing_chars(m->cgroup_root, "/");
2184
2185         /* 2. Show data */
2186         r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, NULL, &path);
2187         if (r < 0)
2188                 return log_error_errno(r, "Cannot find cgroup mount point: %m");
2189
2190         r = cg_unified_flush();
2191         if (r < 0)
2192                 return log_error_errno(r, "Couldn't determine if we are running in the unified hierarchy: %m");
2193
2194         all_unified = cg_all_unified();
2195         if (all_unified < 0)
2196                 return log_error_errno(all_unified, "Couldn't determine whether we are in all unified mode: %m");
2197         if (all_unified > 0)
2198                 log_debug("Unified cgroup hierarchy is located at %s.", path);
2199         else {
2200                 r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
2201                 if (r < 0)
2202                         return log_error_errno(r, "Failed to determine whether systemd's own controller is in unified mode: %m");
2203                 if (r > 0)
2204                         log_debug("Unified cgroup hierarchy is located at %s. Controllers are on legacy hierarchies.", path);
2205                 else
2206                         log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER_LEGACY ". File system hierarchy is at %s.", path);
2207         }
2208
2209 #if 0 /// elogind is not init, and does not install the agent here.
2210         /* 3. Allocate cgroup empty defer event source */
2211         m->cgroup_empty_event_source = sd_event_source_unref(m->cgroup_empty_event_source);
2212         r = sd_event_add_defer(m->event, &m->cgroup_empty_event_source, on_cgroup_empty_event, m);
2213         if (r < 0)
2214                 return log_error_errno(r, "Failed to create cgroup empty event source: %m");
2215
2216         r = sd_event_source_set_priority(m->cgroup_empty_event_source, SD_EVENT_PRIORITY_NORMAL-5);
2217         if (r < 0)
2218                 return log_error_errno(r, "Failed to set priority of cgroup empty event source: %m");
2219
2220         r = sd_event_source_set_enabled(m->cgroup_empty_event_source, SD_EVENT_OFF);
2221         if (r < 0)
2222                 return log_error_errno(r, "Failed to disable cgroup empty event source: %m");
2223
2224         (void) sd_event_source_set_description(m->cgroup_empty_event_source, "cgroup-empty");
2225
2226         /* 4. Install notifier inotify object, or agent */
2227         if (cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) > 0) {
2228
2229                 /* In the unified hierarchy we can get cgroup empty notifications via inotify. */
2230
2231                 m->cgroup_inotify_event_source = sd_event_source_unref(m->cgroup_inotify_event_source);
2232                 safe_close(m->cgroup_inotify_fd);
2233
2234                 m->cgroup_inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
2235                 if (m->cgroup_inotify_fd < 0)
2236                         return log_error_errno(errno, "Failed to create control group inotify object: %m");
2237
2238                 r = sd_event_add_io(m->event, &m->cgroup_inotify_event_source, m->cgroup_inotify_fd, EPOLLIN, on_cgroup_inotify_event, m);
2239                 if (r < 0)
2240                         return log_error_errno(r, "Failed to watch control group inotify object: %m");
2241
2242                 /* Process cgroup empty notifications early, but after service notifications and SIGCHLD. Also
2243                  * see handling of cgroup agent notifications, for the classic cgroup hierarchy support. */
2244                 r = sd_event_source_set_priority(m->cgroup_inotify_event_source, SD_EVENT_PRIORITY_NORMAL-4);
2245                 if (r < 0)
2246                         return log_error_errno(r, "Failed to set priority of inotify event source: %m");
2247
2248                 (void) sd_event_source_set_description(m->cgroup_inotify_event_source, "cgroup-inotify");
2249
2250         } else if (MANAGER_IS_SYSTEM(m) && m->test_run_flags == 0) {
2251
2252                 /* On the legacy hierarchy we only get notifications via cgroup agents. (Which isn't really reliable,
2253                  * since it does not generate events when control groups with children run empty. */
2254
2255                 r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, SYSTEMD_CGROUP_AGENT_PATH);
2256                 if (r < 0)
2257                         log_warning_errno(r, "Failed to install release agent, ignoring: %m");
2258                 else if (r > 0)
2259                         log_debug("Installed release agent.");
2260                 else if (r == 0)
2261                         log_debug("Release agent already installed.");
2262         }
2263
2264         /* 5. Make sure we are in the special "init.scope" unit in the root slice. */
2265         scope_path = strjoina(m->cgroup_root, "/" SPECIAL_INIT_SCOPE);
2266         r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, scope_path, 0);
2267         if (r >= 0) {
2268                 /* Also, move all other userspace processes remaining in the root cgroup into that scope. */
2269                 r = cg_migrate(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, SYSTEMD_CGROUP_CONTROLLER, scope_path, 0);
2270                 if (r < 0)
2271                         log_warning_errno(r, "Couldn't move remaining userspace processes, ignoring: %m");
2272 #else
2273         /* Note:
2274                 * This method is in core, and normally called by systemd
2275                 * being init. As elogind is never init, we can not install
2276                 * our agent here. We do so when mounting our cgroup file
2277                 * system, so only if elogind is its own tiny controller.
2278                 * Further, elogind is not meant to run in systemd init scope. */
2279         if (MANAGER_IS_SYSTEM(m))
2280                 // we are our own cgroup controller
2281                 scope_path = strjoina("");
2282         else if (streq(m->cgroup_root, "/elogind"))
2283                 // root already is our cgroup
2284                 scope_path = strjoina(m->cgroup_root);
2285         else
2286                 // we have to create our own group
2287                 scope_path = strjoina(m->cgroup_root, "/elogind");
2288         r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, scope_path, 0);
2289 #endif // 0
2290         log_debug_elogind("Created control group \"%s\"", scope_path);
2291
2292                 /* 6. And pin it, so that it cannot be unmounted */
2293                 safe_close(m->pin_cgroupfs_fd);
2294                 m->pin_cgroupfs_fd = open(path, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK);
2295                 if (m->pin_cgroupfs_fd < 0)
2296                         return log_error_errno(errno, "Failed to open pin file: %m");
2297
2298 #if 0 /// this is from the cgroup migration above that elogind does not need.
2299         } else if (r < 0 && !m->test_run_flags)
2300                 return log_error_errno(r, "Failed to create %s control group: %m", scope_path);
2301 #endif // 0
2302
2303         /* 7. Always enable hierarchical support if it exists... */
2304         if (!all_unified && m->test_run_flags == 0)
2305                 (void) cg_set_attribute("memory", "/", "memory.use_hierarchy", "1");
2306
2307         /* 8. Figure out which controllers are supported, and log about it */
2308         r = cg_mask_supported(&m->cgroup_supported);
2309         if (r < 0)
2310                 return log_error_errno(r, "Failed to determine supported controllers: %m");
2311         for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++)
2312                 log_debug("Controller '%s' supported: %s", cgroup_controller_to_string(c), yes_no(m->cgroup_supported & CGROUP_CONTROLLER_TO_MASK(c)));
2313
2314         return 0;
2315 }
2316
2317 void manager_shutdown_cgroup(Manager *m, bool delete) {
2318         assert(m);
2319
2320 #if 0 /// elogind is not init
2321         /* We can't really delete the group, since we are in it. But
2322          * let's trim it. */
2323         if (delete && m->cgroup_root && m->test_run_flags != MANAGER_TEST_RUN_MINIMAL)
2324                 (void) cg_trim(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, false);
2325
2326         m->cgroup_empty_event_source = sd_event_source_unref(m->cgroup_empty_event_source);
2327
2328         m->cgroup_inotify_wd_unit = hashmap_free(m->cgroup_inotify_wd_unit);
2329
2330         m->cgroup_inotify_event_source = sd_event_source_unref(m->cgroup_inotify_event_source);
2331         m->cgroup_inotify_fd = safe_close(m->cgroup_inotify_fd);
2332 #endif // 0
2333
2334         m->pin_cgroupfs_fd = safe_close(m->pin_cgroupfs_fd);
2335
2336         m->cgroup_root = mfree(m->cgroup_root);
2337 }
2338
2339 #if 0 /// UNNEEDED by elogind
2340 Unit* manager_get_unit_by_cgroup(Manager *m, const char *cgroup) {
2341         char *p;
2342         Unit *u;
2343
2344         assert(m);
2345         assert(cgroup);
2346
2347         u = hashmap_get(m->cgroup_unit, cgroup);
2348         if (u)
2349                 return u;
2350
2351         p = strdupa(cgroup);
2352         for (;;) {
2353                 char *e;
2354
2355                 e = strrchr(p, '/');
2356                 if (!e || e == p)
2357                         return hashmap_get(m->cgroup_unit, SPECIAL_ROOT_SLICE);
2358
2359                 *e = 0;
2360
2361                 u = hashmap_get(m->cgroup_unit, p);
2362                 if (u)
2363                         return u;
2364         }
2365 }
2366
2367 Unit *manager_get_unit_by_pid_cgroup(Manager *m, pid_t pid) {
2368         _cleanup_free_ char *cgroup = NULL;
2369
2370         assert(m);
2371
2372         if (!pid_is_valid(pid))
2373                 return NULL;
2374
2375         if (cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup) < 0)
2376                 return NULL;
2377
2378         return manager_get_unit_by_cgroup(m, cgroup);
2379 }
2380
2381 Unit *manager_get_unit_by_pid(Manager *m, pid_t pid) {
2382         Unit *u, **array;
2383
2384         assert(m);
2385
2386         /* Note that a process might be owned by multiple units, we return only one here, which is good enough for most
2387          * cases, though not strictly correct. We prefer the one reported by cgroup membership, as that's the most
2388          * relevant one as children of the process will be assigned to that one, too, before all else. */
2389
2390         if (!pid_is_valid(pid))
2391                 return NULL;
2392
2393         if (pid == getpid_cached())
2394                 return hashmap_get(m->units, SPECIAL_INIT_SCOPE);
2395
2396         u = manager_get_unit_by_pid_cgroup(m, pid);
2397         if (u)
2398                 return u;
2399
2400         u = hashmap_get(m->watch_pids, PID_TO_PTR(pid));
2401         if (u)
2402                 return u;
2403
2404         array = hashmap_get(m->watch_pids, PID_TO_PTR(-pid));
2405         if (array)
2406                 return array[0];
2407
2408         return NULL;
2409 }
2410 #endif // 0
2411
2412 #if 0 /// elogind must substitute this with its own variant
2413 int manager_notify_cgroup_empty(Manager *m, const char *cgroup) {
2414         Unit *u;
2415
2416         assert(m);
2417         assert(cgroup);
2418
2419         /* Called on the legacy hierarchy whenever we get an explicit cgroup notification from the cgroup agent process
2420          * or from the --system instance */
2421
2422         log_debug("Got cgroup empty notification for: %s", cgroup);
2423
2424         u = manager_get_unit_by_cgroup(m, cgroup);
2425         if (!u)
2426                 return 0;
2427
2428         unit_add_to_cgroup_empty_queue(u);
2429         return 1;
2430 }
2431 #else
2432 int manager_notify_cgroup_empty(Manager *m, const char *cgroup) {
2433         Session *s;
2434
2435         assert(m);
2436         assert(cgroup);
2437
2438         log_debug("Got cgroup empty notification for: %s", cgroup);
2439
2440         s = hashmap_get(m->sessions, cgroup);
2441
2442         if (s) {
2443                 session_finalize(s);
2444                 session_free(s);
2445         } else
2446                 log_warning("Session not found: %s", cgroup);
2447
2448         return 0;
2449 }
2450 #endif // 0
2451 #if 0 /// UNNEEDED by elogind
2452 int unit_get_memory_current(Unit *u, uint64_t *ret) {
2453         _cleanup_free_ char *v = NULL;
2454         int r;
2455
2456         assert(u);
2457         assert(ret);
2458
2459         if (!UNIT_CGROUP_BOOL(u, memory_accounting))
2460                 return -ENODATA;
2461
2462         if (!u->cgroup_path)
2463                 return -ENODATA;
2464
2465         /* The root cgroup doesn't expose this information, let's get it from /proc instead */
2466         if (unit_has_root_cgroup(u))
2467                 return procfs_memory_get_current(ret);
2468
2469         if ((u->cgroup_realized_mask & CGROUP_MASK_MEMORY) == 0)
2470                 return -ENODATA;
2471
2472         r = cg_all_unified();
2473         if (r < 0)
2474                 return r;
2475         if (r > 0)
2476                 r = cg_get_attribute("memory", u->cgroup_path, "memory.current", &v);
2477         else
2478                 r = cg_get_attribute("memory", u->cgroup_path, "memory.usage_in_bytes", &v);
2479         if (r == -ENOENT)
2480                 return -ENODATA;
2481         if (r < 0)
2482                 return r;
2483
2484         return safe_atou64(v, ret);
2485 }
2486
2487 int unit_get_tasks_current(Unit *u, uint64_t *ret) {
2488         _cleanup_free_ char *v = NULL;
2489         int r;
2490
2491         assert(u);
2492         assert(ret);
2493
2494         if (!UNIT_CGROUP_BOOL(u, tasks_accounting))
2495                 return -ENODATA;
2496
2497         if (!u->cgroup_path)
2498                 return -ENODATA;
2499
2500         /* The root cgroup doesn't expose this information, let's get it from /proc instead */
2501         if (unit_has_root_cgroup(u))
2502                 return procfs_tasks_get_current(ret);
2503
2504         if ((u->cgroup_realized_mask & CGROUP_MASK_PIDS) == 0)
2505                 return -ENODATA;
2506
2507         r = cg_get_attribute("pids", u->cgroup_path, "pids.current", &v);
2508         if (r == -ENOENT)
2509                 return -ENODATA;
2510         if (r < 0)
2511                 return r;
2512
2513         return safe_atou64(v, ret);
2514 }
2515
2516 static int unit_get_cpu_usage_raw(Unit *u, nsec_t *ret) {
2517         _cleanup_free_ char *v = NULL;
2518         uint64_t ns;
2519         int r;
2520
2521         assert(u);
2522         assert(ret);
2523
2524         if (!u->cgroup_path)
2525                 return -ENODATA;
2526
2527         /* The root cgroup doesn't expose this information, let's get it from /proc instead */
2528         if (unit_has_root_cgroup(u))
2529                 return procfs_cpu_get_usage(ret);
2530
2531         r = cg_all_unified();
2532         if (r < 0)
2533                 return r;
2534         if (r > 0) {
2535                 _cleanup_free_ char *val = NULL;
2536                 uint64_t us;
2537
2538                 if ((u->cgroup_realized_mask & CGROUP_MASK_CPU) == 0)
2539                         return -ENODATA;
2540
2541                 r = cg_get_keyed_attribute("cpu", u->cgroup_path, "cpu.stat", STRV_MAKE("usage_usec"), &val);
2542                 if (r < 0)
2543                         return r;
2544                 if (IN_SET(r, -ENOENT, -ENXIO))
2545                         return -ENODATA;
2546
2547                 r = safe_atou64(val, &us);
2548                 if (r < 0)
2549                         return r;
2550
2551                 ns = us * NSEC_PER_USEC;
2552         } else {
2553                 if ((u->cgroup_realized_mask & CGROUP_MASK_CPUACCT) == 0)
2554                         return -ENODATA;
2555
2556                 r = cg_get_attribute("cpuacct", u->cgroup_path, "cpuacct.usage", &v);
2557                 if (r == -ENOENT)
2558                         return -ENODATA;
2559                 if (r < 0)
2560                         return r;
2561
2562                 r = safe_atou64(v, &ns);
2563                 if (r < 0)
2564                         return r;
2565         }
2566
2567         *ret = ns;
2568         return 0;
2569 }
2570
2571 int unit_get_cpu_usage(Unit *u, nsec_t *ret) {
2572         nsec_t ns;
2573         int r;
2574
2575         assert(u);
2576
2577         /* Retrieve the current CPU usage counter. This will subtract the CPU counter taken when the unit was
2578          * started. If the cgroup has been removed already, returns the last cached value. To cache the value, simply
2579          * call this function with a NULL return value. */
2580
2581         if (!UNIT_CGROUP_BOOL(u, cpu_accounting))
2582                 return -ENODATA;
2583
2584         r = unit_get_cpu_usage_raw(u, &ns);
2585         if (r == -ENODATA && u->cpu_usage_last != NSEC_INFINITY) {
2586                 /* If we can't get the CPU usage anymore (because the cgroup was already removed, for example), use our
2587                  * cached value. */
2588
2589                 if (ret)
2590                         *ret = u->cpu_usage_last;
2591                 return 0;
2592         }
2593         if (r < 0)
2594                 return r;
2595
2596         if (ns > u->cpu_usage_base)
2597                 ns -= u->cpu_usage_base;
2598         else
2599                 ns = 0;
2600
2601         u->cpu_usage_last = ns;
2602         if (ret)
2603                 *ret = ns;
2604
2605         return 0;
2606 }
2607
2608 int unit_get_ip_accounting(
2609                 Unit *u,
2610                 CGroupIPAccountingMetric metric,
2611                 uint64_t *ret) {
2612
2613         uint64_t value;
2614         int fd, r;
2615
2616         assert(u);
2617         assert(metric >= 0);
2618         assert(metric < _CGROUP_IP_ACCOUNTING_METRIC_MAX);
2619         assert(ret);
2620
2621         if (!UNIT_CGROUP_BOOL(u, ip_accounting))
2622                 return -ENODATA;
2623
2624         fd = IN_SET(metric, CGROUP_IP_INGRESS_BYTES, CGROUP_IP_INGRESS_PACKETS) ?
2625                 u->ip_accounting_ingress_map_fd :
2626                 u->ip_accounting_egress_map_fd;
2627         if (fd < 0)
2628                 return -ENODATA;
2629
2630         if (IN_SET(metric, CGROUP_IP_INGRESS_BYTES, CGROUP_IP_EGRESS_BYTES))
2631                 r = bpf_firewall_read_accounting(fd, &value, NULL);
2632         else
2633                 r = bpf_firewall_read_accounting(fd, NULL, &value);
2634         if (r < 0)
2635                 return r;
2636
2637         /* Add in additional metrics from a previous runtime. Note that when reexecing/reloading the daemon we compile
2638          * all BPF programs and maps anew, but serialize the old counters. When deserializing we store them in the
2639          * ip_accounting_extra[] field, and add them in here transparently. */
2640
2641         *ret = value + u->ip_accounting_extra[metric];
2642
2643         return r;
2644 }
2645
2646 int unit_reset_cpu_accounting(Unit *u) {
2647         nsec_t ns;
2648         int r;
2649
2650         assert(u);
2651
2652         u->cpu_usage_last = NSEC_INFINITY;
2653
2654         r = unit_get_cpu_usage_raw(u, &ns);
2655         if (r < 0) {
2656                 u->cpu_usage_base = 0;
2657                 return r;
2658         }
2659
2660         u->cpu_usage_base = ns;
2661         return 0;
2662 }
2663
2664 int unit_reset_ip_accounting(Unit *u) {
2665         int r = 0, q = 0;
2666
2667         assert(u);
2668
2669         if (u->ip_accounting_ingress_map_fd >= 0)
2670                 r = bpf_firewall_reset_accounting(u->ip_accounting_ingress_map_fd);
2671
2672         if (u->ip_accounting_egress_map_fd >= 0)
2673                 q = bpf_firewall_reset_accounting(u->ip_accounting_egress_map_fd);
2674
2675         zero(u->ip_accounting_extra);
2676
2677         return r < 0 ? r : q;
2678 }
2679
2680 void unit_invalidate_cgroup(Unit *u, CGroupMask m) {
2681         assert(u);
2682
2683         if (!UNIT_HAS_CGROUP_CONTEXT(u))
2684                 return;
2685
2686         if (m == 0)
2687                 return;
2688
2689         /* always invalidate compat pairs together */
2690         if (m & (CGROUP_MASK_IO | CGROUP_MASK_BLKIO))
2691                 m |= CGROUP_MASK_IO | CGROUP_MASK_BLKIO;
2692
2693         if (m & (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT))
2694                 m |= CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT;
2695
2696         if ((u->cgroup_realized_mask & m) == 0) /* NOP? */
2697                 return;
2698
2699         u->cgroup_realized_mask &= ~m;
2700         unit_add_to_cgroup_realize_queue(u);
2701 }
2702
2703 void unit_invalidate_cgroup_bpf(Unit *u) {
2704         assert(u);
2705
2706         if (!UNIT_HAS_CGROUP_CONTEXT(u))
2707                 return;
2708
2709         if (u->cgroup_bpf_state == UNIT_CGROUP_BPF_INVALIDATED) /* NOP? */
2710                 return;
2711
2712         u->cgroup_bpf_state = UNIT_CGROUP_BPF_INVALIDATED;
2713         unit_add_to_cgroup_realize_queue(u);
2714
2715         /* If we are a slice unit, we also need to put compile a new BPF program for all our children, as the IP access
2716          * list of our children includes our own. */
2717         if (u->type == UNIT_SLICE) {
2718                 Unit *member;
2719                 Iterator i;
2720                 void *v;
2721
2722                 HASHMAP_FOREACH_KEY(v, member, u->dependencies[UNIT_BEFORE], i) {
2723                         if (member == u)
2724                                 continue;
2725
2726                         if (UNIT_DEREF(member->slice) != u)
2727                                 continue;
2728
2729                         unit_invalidate_cgroup_bpf(member);
2730                 }
2731         }
2732 }
2733
2734 bool unit_cgroup_delegate(Unit *u) {
2735         CGroupContext *c;
2736
2737         assert(u);
2738
2739         if (!UNIT_VTABLE(u)->can_delegate)
2740                 return false;
2741
2742         c = unit_get_cgroup_context(u);
2743         if (!c)
2744                 return false;
2745
2746         return c->delegate;
2747 }
2748
2749 void manager_invalidate_startup_units(Manager *m) {
2750         Iterator i;
2751         Unit *u;
2752
2753         assert(m);
2754
2755         SET_FOREACH(u, m->startup_units, i)
2756                 unit_invalidate_cgroup(u, CGROUP_MASK_CPU|CGROUP_MASK_IO|CGROUP_MASK_BLKIO);
2757 }
2758
2759 static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = {
2760         [CGROUP_AUTO] = "auto",
2761         [CGROUP_CLOSED] = "closed",
2762         [CGROUP_STRICT] = "strict",
2763 };
2764
2765 DEFINE_STRING_TABLE_LOOKUP(cgroup_device_policy, CGroupDevicePolicy);
2766 #endif // 0