X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Fcgroup-util.c;h=8d3bdce0f576fa2184cf317e4758259b1e22a9e2;hb=e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cd;hp=b2fb324a18c995255e954ff2bc5e644c5d8f0ba9;hpb=3474ae3c7e1981301d0b35bc89d759ca13f06e8f;p=elogind.git diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c index b2fb324a1..8d3bdce0f 100644 --- a/src/shared/cgroup-util.c +++ b/src/shared/cgroup-util.c @@ -34,17 +34,19 @@ #include "set.h" #include "macro.h" #include "util.h" +#include "path-util.h" +#include "strv.h" int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) { char *fs; int r; FILE *f; - assert(controller); assert(path); assert(_f); - if ((r = cg_get_path(controller, path, "cgroup.procs", &fs)) < 0) + r = cg_get_path(controller, path, "cgroup.procs", &fs); + if (r < 0) return r; f = fopen(fs, "re"); @@ -62,11 +64,11 @@ int cg_enumerate_tasks(const char *controller, const char *path, FILE **_f) { int r; FILE *f; - assert(controller); assert(path); assert(_f); - if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0) + r = cg_get_path(controller, path, "tasks", &fs); + if (r < 0) return r; f = fopen(fs, "re"); @@ -106,13 +108,13 @@ int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d) { int r; DIR *d; - assert(controller); assert(path); assert(_d); /* This is not recursive! */ - if ((r = cg_get_path(controller, path, NULL, &fs)) < 0) + r = cg_get_path(controller, path, NULL, &fs); + if (r < 0) return r; d = opendir(fs); @@ -513,16 +515,26 @@ static const char *normalize_controller(const char *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); + char *t = NULL; + + if (!(controller || path)) + return -EINVAL; + + if (controller) { + 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); + } else { + if (path && suffix) + t = join(path, "/", suffix, NULL); + else if (path) + t = strdup(path); + } if (!t) return -ENOMEM; @@ -537,12 +549,8 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch const char *p; static __thread bool good = false; - assert(controller); assert(fs); - if (isempty(controller)) - return -EINVAL; - if (_unlikely_(!good)) { int r; @@ -554,14 +562,27 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch good = true; } - p = normalize_controller(controller); - + p = controller ? normalize_controller(controller) : NULL; return join_path(p, path, suffix, fs); } +static int check(const char *p) { + char *cc; + + assert(p); + + /* 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 0; +} + int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs) { const char *p; - char *cc; + int r; assert(controller); assert(fs); @@ -569,13 +590,13 @@ int cg_get_path_and_check(const char *controller, const char *path, const char * if (isempty(controller)) return -EINVAL; + /* Normalize the controller syntax */ p = normalize_controller(controller); /* 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; + r = check(p); + if (r < 0) + return r; return join_path(p, path, suffix, fs); } @@ -653,7 +674,7 @@ int cg_delete(const char *controller, const char *path) { assert(controller); assert(path); - if ((r = parent_of_path(path, &parent)) < 0) + if ((r = path_get_parent(path, &parent)) < 0) return r; r = cg_migrate_recursive(controller, path, parent, false, true); @@ -883,20 +904,22 @@ finish: } int cg_is_empty(const char *controller, const char *path, bool ignore_self) { - pid_t pid = 0; + pid_t pid = 0, self_pid; int r; FILE *f = NULL; bool found = false; - assert(controller); assert(path); - if ((r = cg_enumerate_tasks(controller, path, &f)) < 0) + r = cg_enumerate_tasks(controller, path, &f); + if (r < 0) return r == -ENOENT ? 1 : r; + self_pid = getpid(); + while ((r = cg_read_pid(f, &pid)) > 0) { - if (ignore_self && pid == getpid()) + if (ignore_self && pid == self_pid) continue; found = true; @@ -916,13 +939,14 @@ int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_ DIR *d = NULL; char *fn; - assert(controller); assert(path); - if ((r = cg_is_empty(controller, path, ignore_self)) <= 0) + r = cg_is_empty(controller, path, ignore_self); + if (r <= 0) return r; - if ((r = cg_enumerate_subgroups(controller, path, &d)) < 0) + r = cg_enumerate_subgroups(controller, path, &d); + if (r < 0) return r == -ENOENT ? 1 : r; while ((r = cg_read_subgroup(d, &fn)) > 0) { @@ -1042,11 +1066,11 @@ int cg_fix_path(const char *path, char **result) { assert(result); /* First check if it already is a filesystem path */ - if (path_is_absolute(path) && - path_startswith(path, "/sys/fs/cgroup") && + if (path_startswith(path, "/sys/fs/cgroup") && access(path, F_OK) >= 0) { - if (!(t = strdup(path))) + t = strdup(path); + if (!t) return -ENOMEM; *result = t; @@ -1054,7 +1078,8 @@ int cg_fix_path(const char *path, char **result) { } /* Otherwise treat it as cg spec */ - if ((r = cg_split_spec(path, &c, &p)) < 0) + r = cg_split_spec(path, &c, &p); + if (r < 0) return r; r = cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result); @@ -1091,3 +1116,36 @@ int cg_get_user_path(char **path) { *path = p; return 0; } + +char **cg_shorten_controllers(char **controllers) { + char **f, **t; + + controllers = strv_uniq(controllers); + + if (!controllers) + return controllers; + + for (f = controllers, t = controllers; *f; f++) { + int r; + const char *p; + + if (streq(*f, "systemd") || streq(*f, SYSTEMD_CGROUP_CONTROLLER)) { + free(*f); + continue; + } + + p = normalize_controller(*f); + + r = check(p); + if (r < 0) { + log_debug("Controller %s is not available, removing from controllers list.", *f); + free(*f); + continue; + } + + *(t++) = *f; + } + + *t = NULL; + return controllers; +}