]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/nspawn/nspawn-cgroup.c
treewide: fix typos and remove accidental repetition of words
[thirdparty/systemd.git] / src / nspawn / nspawn-cgroup.c
CommitLineData
34829a32
LP
1/***
2 This file is part of systemd.
3
4 Copyright 2015 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
20#include <sys/mount.h>
21
b5efdb8a 22#include "alloc-util.h"
34829a32 23#include "cgroup-util.h"
3ffd4af2 24#include "fd-util.h"
07630cea
LP
25#include "fileio.h"
26#include "mkdir.h"
3ffd4af2 27#include "nspawn-cgroup.h"
07630cea
LP
28#include "string-util.h"
29#include "strv.h"
30#include "util.h"
34829a32
LP
31
32int chown_cgroup(pid_t pid, uid_t uid_shift) {
33 _cleanup_free_ char *path = NULL, *fs = NULL;
34 _cleanup_close_ int fd = -1;
35 const char *fn;
36 int r;
37
38 r = cg_pid_get_path(NULL, pid, &path);
39 if (r < 0)
40 return log_error_errno(r, "Failed to get container cgroup path: %m");
41
42 r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, NULL, &fs);
43 if (r < 0)
44 return log_error_errno(r, "Failed to get file system path for container cgroup: %m");
45
46 fd = open(fs, O_RDONLY|O_CLOEXEC|O_DIRECTORY);
47 if (fd < 0)
48 return log_error_errno(errno, "Failed to open %s: %m", fs);
49
50 FOREACH_STRING(fn,
51 ".",
52 "tasks",
53 "notify_on_release",
54 "cgroup.procs",
aa3be0dd 55 "cgroup.events",
34829a32
LP
56 "cgroup.clone_children",
57 "cgroup.controllers",
ab2c3861 58 "cgroup.subtree_control")
34829a32
LP
59 if (fchownat(fd, fn, uid_shift, uid_shift, 0) < 0)
60 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
61 "Failed to chown() cgroup file %s, ignoring: %m", fn);
62
63 return 0;
64}
65
66int sync_cgroup(pid_t pid, bool unified_requested) {
67 _cleanup_free_ char *cgroup = NULL;
68 char tree[] = "/tmp/unifiedXXXXXX", pid_string[DECIMAL_STR_MAX(pid) + 1];
69 bool undo_mount = false;
70 const char *fn;
71 int unified, r;
72
73 unified = cg_unified();
74 if (unified < 0)
998fdc16 75 return log_error_errno(unified, "Failed to determine whether the unified hierarchy is used: %m");
34829a32
LP
76
77 if ((unified > 0) == unified_requested)
78 return 0;
79
80 /* When the host uses the legacy cgroup setup, but the
81 * container shall use the unified hierarchy, let's make sure
82 * we copy the path from the name=systemd hierarchy into the
83 * unified hierarchy. Similar for the reverse situation. */
84
85 r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup);
86 if (r < 0)
87 return log_error_errno(r, "Failed to get control group of " PID_FMT ": %m", pid);
88
89 /* In order to access the unified hierarchy we need to mount it */
90 if (!mkdtemp(tree))
91 return log_error_errno(errno, "Failed to generate temporary mount point for unified hierarchy: %m");
92
93 if (unified)
94 r = mount("cgroup", tree, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, "none,name=systemd,xattr");
95 else
09961995 96 r = mount("cgroup", tree, "cgroup2", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL);
34829a32
LP
97 if (r < 0) {
98 r = log_error_errno(errno, "Failed to mount unified hierarchy: %m");
99 goto finish;
100 }
101
102 undo_mount = true;
103
104 fn = strjoina(tree, cgroup, "/cgroup.procs");
105 (void) mkdir_parents(fn, 0755);
106
107 sprintf(pid_string, PID_FMT, pid);
108 r = write_string_file(fn, pid_string, 0);
109 if (r < 0)
110 log_error_errno(r, "Failed to move process: %m");
111
112finish:
113 if (undo_mount)
114 (void) umount(tree);
115
116 (void) rmdir(tree);
117 return r;
118}
119
120int create_subcgroup(pid_t pid, bool unified_requested) {
121 _cleanup_free_ char *cgroup = NULL;
122 const char *child;
123 int unified, r;
124 CGroupMask supported;
125
61233823 126 /* In the unified hierarchy inner nodes may only contain
34829a32
LP
127 * subgroups, but not processes. Hence, if we running in the
128 * unified hierarchy and the container does the same, and we
129 * did not create a scope unit for the container move us and
130 * the container into two separate subcgroups. */
131
132 if (!unified_requested)
133 return 0;
134
135 unified = cg_unified();
136 if (unified < 0)
998fdc16 137 return log_error_errno(unified, "Failed to determine whether the unified hierarchy is used: %m");
34829a32
LP
138 if (unified == 0)
139 return 0;
140
141 r = cg_mask_supported(&supported);
142 if (r < 0)
143 return log_error_errno(r, "Failed to determine supported controllers: %m");
144
145 r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup);
146 if (r < 0)
147 return log_error_errno(r, "Failed to get our control group: %m");
148
149 child = strjoina(cgroup, "/payload");
150 r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, child, pid);
151 if (r < 0)
152 return log_error_errno(r, "Failed to create %s subcgroup: %m", child);
153
154 child = strjoina(cgroup, "/supervisor");
155 r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, child, 0);
156 if (r < 0)
157 return log_error_errno(r, "Failed to create %s subcgroup: %m", child);
158
159 /* Try to enable as many controllers as possible for the new payload. */
160 (void) cg_enable_everywhere(supported, supported, cgroup);
161 return 0;
162}