From b7820c1e2dbb3b03929d39beff14e2180cd0de3b Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Sat, 14 Apr 2012 02:15:13 +0200
Subject: [PATCH] cgroup: if a controller is not available don't try to create
cgroups in its hierarchy (cherry picked from commit
3474ae3c7e1981301d0b35bc89d759ca13f06e8f)
Conflicts:
src/shared/cgroup-label.c
---
src/cgroup-util.c | 85 +++++++++++++++++++++++++++++++++++------------------
src/cgroup-util.h | 1 +
src/cgroup.c | 6 ++-
3 files changed, 61 insertions(+), 31 deletions(-)
diff --git a/src/cgroup-util.c b/src/cgroup-util.c
index f74280f..aeadf50 100644
--- a/src/cgroup-util.c
+++ b/src/cgroup-util.c
@@ -502,14 +502,47 @@ finish:
return ret;
}
+static const char *normalize_controller(const char *controller) {
+
+ if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
+ return "systemd";
+ else if (startswith(controller, "name="))
+ return controller + 5;
+ else
+ return controller;
+}
+
+static int join_path(const char *controller, const char *path, const char *suffix, char **fs) {
+ char *t;
+
+ if (path && suffix)
+ t = join("/sys/fs/cgroup/", controller, "/", path, "/", suffix, NULL);
+ else if (path)
+ t = join("/sys/fs/cgroup/", controller, "/", path, NULL);
+ else if (suffix)
+ t = join("/sys/fs/cgroup/", controller, "/", suffix, NULL);
+ else
+ t = join("/sys/fs/cgroup/", controller, NULL);
+
+ if (!t)
+ return -ENOMEM;
+
+ path_kill_slashes(t);
+
+ *fs = t;
+ return 0;
+}
+
int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) {
const char *p;
- char *t;
static __thread bool good = false;
assert(controller);
assert(fs);
+ if (isempty(controller))
+ return -EINVAL;
+
if (_unlikely_(!good)) {
int r;
@@ -521,38 +554,30 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch
good = true;
}
- if (isempty(controller))
- return -EINVAL;
+ p = normalize_controller(controller);
- /* This is a very minimal lookup from controller names to
- * paths. Since we have mounted most hierarchies ourselves
- * should be kinda safe, but eventually we might want to
- * extend this to have a fallback to actually check
- * /proc/mounts. Might need caching then. */
+ return join_path(p, path, suffix, fs);
+}
- if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
- p = "systemd";
- else if (startswith(controller, "name="))
- p = controller + 5;
- else
- p = controller;
+int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs) {
+ const char *p;
+ char *cc;
- if (path && suffix)
- t = join("/sys/fs/cgroup/", p, "/", path, "/", suffix, NULL);
- else if (path)
- t = join("/sys/fs/cgroup/", p, "/", path, NULL);
- else if (suffix)
- t = join("/sys/fs/cgroup/", p, "/", suffix, NULL);
- else
- t = join("/sys/fs/cgroup/", p, NULL);
+ assert(controller);
+ assert(fs);
- if (!t)
- return -ENOMEM;
+ if (isempty(controller))
+ return -EINVAL;
- path_kill_slashes(t);
+ p = normalize_controller(controller);
- *fs = t;
- return 0;
+ /* Check if this controller actually really exists */
+ cc = alloca(sizeof("/sys/fs/cgroup/") + strlen(p));
+ strcpy(stpcpy(cc, "/sys/fs/cgroup/"), p);
+ if (access(cc, F_OK) < 0)
+ return -errno;
+
+ return join_path(p, path, suffix, fs);
}
static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
@@ -644,7 +669,8 @@ int cg_create(const char *controller, const char *path) {
assert(controller);
assert(path);
- if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
+ r = cg_get_path_and_check(controller, path, NULL, &fs);
+ if (r < 0)
return r;
r = mkdir_parents(fs, 0755);
@@ -672,7 +698,8 @@ int cg_attach(const char *controller, const char *path, pid_t pid) {
assert(path);
assert(pid >= 0);
- if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
+ r = cg_get_path_and_check(controller, path, "tasks", &fs);
+ if (r < 0)
return r;
if (pid == 0)
diff --git a/src/cgroup-util.h b/src/cgroup-util.h
index f09373b..8a83773 100644
--- a/src/cgroup-util.h
+++ b/src/cgroup-util.h
@@ -48,6 +48,7 @@ int cg_join_spec(const char *controller, const char *path, char **spec);
int cg_fix_path(const char *path, char **result);
int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs);
+int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs);
int cg_get_by_pid(const char *controller, pid_t pid, char **path);
int cg_trim(const char *controller, const char *path, bool delete_root);
diff --git a/src/cgroup.c b/src/cgroup.c
index d7c5bdb..2711863 100644
--- a/src/cgroup.c
+++ b/src/cgroup.c
@@ -302,7 +302,8 @@ int manager_setup_cgroup(Manager *m) {
}
/* 2. Show data */
- if ((r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, NULL, &path)) < 0) {
+ r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, NULL, &path);
+ if (r < 0) {
log_error("Cannot find cgroup mount point: %s", strerror(-r));
goto finish;
}
@@ -310,7 +311,8 @@ int manager_setup_cgroup(Manager *m) {
log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER ". File system hierarchy is at %s.", path);
/* 3. Install agent */
- if ((r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, SYSTEMD_CGROUP_AGENT_PATH)) < 0)
+ r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, SYSTEMD_CGROUP_AGENT_PATH);
+ if (r < 0)
log_warning("Failed to install release agent, ignoring: %s", strerror(-r));
else if (r > 0)
log_debug("Installed release agent.");