1
From 3f2044cb5764c6cf568f7b016a5a1e639dcab129 Mon Sep 17 00:00:00 2001
2
From: Serge Hallyn <serge.hallyn@ubuntu.com>
3
Date: Mon, 17 Feb 2014 15:01:05 -0600
4
Subject: [PATCH 1/1] allow passing in extra mounts
6
cgroup mounts like the 'none,name=systemd' mount do not show up in
7
/proc/cgroups. So allow the user to specify a list of such unbound
8
cgroup subsystems to mount. I.e.
10
cgmanager -m name=systemd,name=yyy
12
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
14
cgmanager.c | 13 +++++-
15
fs.c | 149 ++++++++++++++++++++++++++++++++++++++++++------------------
17
3 files changed, 117 insertions(+), 47 deletions(-)
19
diff --git a/cgmanager.c b/cgmanager.c
20
index e203da1..6fe428a 100644
23
@@ -604,6 +604,15 @@ int get_tasks_main(void *parent, const char *controller, const char *cgroup,
24
return file_read_pids(parent, path, pids);
27
+char *extra_cgroup_mounts;
30
+my_setter (NihOption *option, const char *arg)
32
+ extra_cgroup_mounts = NIH_MUST( strdup(arg) );
39
@@ -611,6 +620,8 @@ int get_tasks_main(void *parent, const char *controller, const char *cgroup,
40
* Command-line options accepted by this program.
42
static NihOption options[] = {
43
+ { 'm', "mount", N_("Extra subsystems to mount"),
44
+ NULL, "subsystems to mount", NULL, my_setter },
45
{ 0, "daemon", N_("Detach and run in the background"),
46
NULL, NULL, &daemonise, NULL },
48
@@ -708,7 +719,7 @@ main (int argc, char *argv[])
50
nih_assert (server != NULL);
52
- if (setup_cgroup_mounts() < 0) {
53
+ if (setup_cgroup_mounts(extra_cgroup_mounts) < 0) {
54
nih_fatal ("Failed to set up cgroup mounts");
57
diff --git a/fs.c b/fs.c
58
index 313a6c2..b6dd4fd 100644
61
@@ -122,6 +122,79 @@ static void set_use_hierarchy(const char *path)
65
+static bool do_mount_subsys(char *s)
67
+ struct controller_mounts *tmp;
68
+ char *src, dest[MAXPATHLEN], *controller;
70
+ size_t len = strlen(s);
72
+ if (len > MAXPATHLEN) {
73
+ nih_fatal("bad controller type: %s", s);
76
+ if ((controller = strchr(s, '='))) {
77
+ /* this is something like 'name=systemd' */
78
+ src = alloca(len+6);
79
+ /* so for controller we want 'systemd' */
81
+ /* and for source we want "none,name=systemd" */
82
+ snprintf(src, len+6, "none,%s", s);
88
+ ret = snprintf(dest, MAXPATHLEN, "%s/%s", base_path, src);
89
+ if (ret < 0 || ret >= MAXPATHLEN) {
90
+ nih_fatal("Error calculating pathname for %s and %s", base_path, src);
94
+ if (mkdir(dest, 0755) < 0 && errno != EEXIST) {
95
+ nih_fatal("Failed to create %s: %s", dest, strerror(errno));
99
+ if ((ret = mount(src, dest, "cgroup", 0, src)) < 0) {
100
+ nih_fatal("Failed mounting %s: %s", s, strerror(errno));
104
+ tmp = realloc(all_mounts, (num_controllers+1) * sizeof(*all_mounts));
106
+ nih_fatal("Out of memory mounting controllers");
110
+ all_mounts[num_controllers].controller = strdup(controller);
111
+ if (!all_mounts[num_controllers].controller) {
112
+ nih_fatal("Out of memory mounting controllers");
115
+ all_mounts[num_controllers].options = NULL;
116
+ all_mounts[num_controllers].path = strdup(dest);
117
+ if (!all_mounts[num_controllers].path) {
118
+ nih_fatal("Out of memory mounting controllers");
121
+ nih_info(_("Mounted %s onto %s"),
122
+ all_mounts[num_controllers].controller,
123
+ all_mounts[num_controllers].path);
124
+ if (strcmp(all_mounts[num_controllers].controller, "cpuset") == 0) {
125
+ set_clone_children(dest); // TODO make this optional?
126
+ nih_info(_("set clone_children"));
127
+ } else if (strcmp(all_mounts[num_controllers].controller, "memory") == 0) {
128
+ set_use_hierarchy(dest); // TODO make this optional?
129
+ nih_info(_("set memory.use_hierarchy"));
139
* Mount the cgroup filesystems and record the information.
140
* This should take configuration data from /etc. For now,
141
@@ -134,7 +207,7 @@ static void set_use_hierarchy(const char *path)
142
* . any mount options (per-controller)
143
* . values for sane_behavior, use_hierarchy, and clone_children
145
-int setup_cgroup_mounts(void)
146
+int setup_cgroup_mounts(char *extra_mounts)
150
@@ -148,14 +221,23 @@ int setup_cgroup_mounts(void)
151
nih_fatal("Error setting up base cgroup path");
155
+ if (extra_mounts) {
157
+ for (e = strtok(extra_mounts, ","); e; e = strtok(NULL, ",")) {
158
+ if (!do_mount_subsys(e)) {
159
+ nih_fatal("Error loading subsystem \"%s\"", e);
165
if ((cgf = fopen("/proc/cgroups", "r")) == NULL) {
166
nih_fatal ("Error opening /proc/cgroups: %s", strerror(errno));
169
while (fgets(line, 400, cgf)) {
171
- struct controller_mounts *tmp;
172
- char dest[MAXPATHLEN];
176
@@ -172,50 +254,12 @@ int setup_cgroup_mounts(void)
180
- ret = snprintf(dest, MAXPATHLEN, "%s/%s", base_path, line);
181
- if (ret < 0 || ret >= MAXPATHLEN) {
182
- nih_fatal("Error calculating pathname for %s and %s", base_path, line);
186
- if (mkdir(dest, 0755) < 0 && errno != EEXIST) {
187
- nih_fatal("Failed to create %s: %s", dest, strerror(errno));
189
+ if (!do_mount_subsys(line)) {
190
+ nih_fatal("Error mounting subsystem %s", line);
194
- if ((ret = mount(line, dest, "cgroup", 0, line)) < 0) {
195
- nih_fatal("Failed mounting %s: %s", line, strerror(errno));
199
- tmp = realloc(all_mounts, (num_controllers+1) * sizeof(*all_mounts));
201
- nih_fatal("Out of memory mounting controllers");
205
- all_mounts[num_controllers].controller = strdup(line);
206
- if (!all_mounts[num_controllers].controller) {
207
- nih_fatal("Out of memory mounting controllers");
210
- all_mounts[num_controllers].options = NULL;
211
- all_mounts[num_controllers].path = strdup(dest);
212
- if (!all_mounts[num_controllers].path) {
213
- nih_fatal("Out of memory mounting controllers");
216
- nih_info(_("Mounted %s onto %s"),
217
- all_mounts[num_controllers].controller,
218
- all_mounts[num_controllers].path);
219
- if (strcmp(all_mounts[num_controllers].controller, "cpuset") == 0) {
220
- set_clone_children(dest); // TODO make this optional?
221
- nih_info(_("set clone_children"));
222
- } else if (strcmp(all_mounts[num_controllers].controller, "memory") == 0) {
223
- set_use_hierarchy(dest); // TODO make this optional?
224
- nih_info(_("set memory.use_hierarchy"));
228
nih_info(_("mounted %d controllers"), num_controllers);
230
@@ -233,6 +277,21 @@ static inline void drop_newlines(char *s)
234
+ * The user will pass in 'cpuset' or 'systemd'. /proc/self/cgroup will
235
+ * show 'cpuset:' or 'name=systemd:'. We have to account for that.
237
+static bool is_same_controller(const char *cmp, const char *cnt)
239
+ if (strcmp(cmp, cnt) == 0)
241
+ if (strncmp(cmp, "name=", 5) != 0)
243
+ if (strcmp(cmp+5, cnt) == 0)
249
* pid_cgroup: return the cgroup of @pid for @controller.
250
* retv must be a (at least) MAXPATHLEN size buffer into
251
* which the answer will be copied.
252
@@ -258,7 +317,7 @@ static inline char *pid_cgroup(pid_t pid, const char *controller, char *retv)
255
for (; (token = strtok_r(c1, ",", &saveptr)); c1 = NULL) {
256
- if (strcmp(token, controller) != 0)
257
+ if (!is_same_controller(token, controller))
259
if (strlen(c2+1) + 1 > MAXPATHLEN) {
260
nih_error("cgroup name too long");
261
diff --git a/fs.h b/fs.h
262
index 3322e62..b5d3868 100644
266
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
269
-int setup_cgroup_mounts(void);
270
+int setup_cgroup_mounts(char *extra_mounts);
271
bool compute_pid_cgroup(pid_t pid, const char *controller, const char *cgroup, char *path);
272
bool may_access(pid_t pid, uid_t uid, gid_t gid, const char *path, int mode);
273
void get_pid_creds(pid_t pid, uid_t *uid, gid_t *gid);