X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Fcgroup-util.c;h=b0d378de5ade1e577a0c7f86cd7b294b3e0ec709;hb=19e65613563dd9c14cf1ce58aa6e151de8fb90c2;hp=d34c142729da00f229d4e9dc103fd4ba2c5711d1;hpb=018ef268b1667ba0dbfc15804ab33deed6092147;p=elogind.git diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c index d34c14272..b0d378de5 100644 --- a/src/shared/cgroup-util.c +++ b/src/shared/cgroup-util.c @@ -34,6 +34,7 @@ #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) { @@ -521,16 +522,16 @@ static int join_path(const char *controller, const char *path, const char *suffi if (controller) { if (path && suffix) - t = join("/sys/fs/cgroup/", controller, "/", path, "/", suffix, NULL); + t = strjoin("/sys/fs/cgroup/", controller, "/", path, "/", suffix, NULL); else if (path) - t = join("/sys/fs/cgroup/", controller, "/", path, NULL); + t = strjoin("/sys/fs/cgroup/", controller, "/", path, NULL); else if (suffix) - t = join("/sys/fs/cgroup/", controller, "/", suffix, NULL); + t = strjoin("/sys/fs/cgroup/", controller, "/", suffix, NULL); else - t = join("/sys/fs/cgroup/", controller, NULL); + t = strjoin("/sys/fs/cgroup/", controller, NULL); } else { if (path && suffix) - t = join(path, "/", suffix, NULL); + t = strjoin(path, "/", suffix, NULL); else if (path) t = strdup(path); } @@ -565,9 +566,23 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch 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); @@ -575,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); } @@ -659,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); @@ -1111,17 +1126,18 @@ char **cg_shorten_controllers(char **controllers) { return controllers; for (f = controllers, t = controllers; *f; f++) { - char *cc; + int r; + const char *p; if (streq(*f, "systemd") || streq(*f, SYSTEMD_CGROUP_CONTROLLER)) { free(*f); continue; } - cc = alloca(sizeof("/sys/fs/cgroup/") + strlen(*f)); - strcpy(stpcpy(cc, "/sys/fs/cgroup/"), *f); + p = normalize_controller(*f); - if (access(cc, F_OK) < 0) { + r = check(p); + if (r < 0) { log_debug("Controller %s is not available, removing from controllers list.", *f); free(*f); continue; @@ -1133,3 +1149,108 @@ char **cg_shorten_controllers(char **controllers) { *t = NULL; return controllers; } + +int cg_pid_get_cgroup(pid_t pid, char **root, char **cgroup) { + char *cg_process, *cg_init, *p; + int r; + + assert(pid >= 0); + + if (pid == 0) + pid = getpid(); + + r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &cg_process); + if (r < 0) + return r; + + r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &cg_init); + if (r < 0) { + free(cg_process); + return r; + } + + if (endswith(cg_init, "/system")) + cg_init[strlen(cg_init)-7] = 0; + else if (streq(cg_init, "/")) + cg_init[0] = 0; + + if (startswith(cg_process, cg_init)) + p = cg_process + strlen(cg_init); + else + p = cg_process; + + free(cg_init); + + if (cgroup) { + char* c; + + c = strdup(p); + if (!c) { + free(cg_process); + return -ENOMEM; + } + + *cgroup = c; + } + + if (root) { + cg_process[p-cg_process] = 0; + *root = cg_process; + } else + free(cg_process); + + return 0; +} + +int cg_pid_get_unit(pid_t pid, char **unit) { + int r; + char *cgroup, *p, *at, *b; + size_t k; + + assert(pid >= 0); + assert(unit); + + r = cg_pid_get_cgroup(pid, NULL, &cgroup); + if (r < 0) + return r; + + if (!startswith(cgroup, "/system/")) { + free(cgroup); + return -ENOENT; + } + + p = cgroup + 8; + k = strcspn(p, "/"); + + at = memchr(p, '@', k); + if (at && at[1] == '.') { + size_t j; + + /* This is a templated service */ + if (p[k] != '/') { + free(cgroup); + return -EIO; + } + + j = strcspn(p+k+1, "/"); + + b = malloc(k + j + 1); + + if (b) { + memcpy(b, p, at - p + 1); + memcpy(b + (at - p) + 1, p + k + 1, j); + memcpy(b + (at - p) + 1 + j, at + 1, k - (at - p) - 1); + b[k+j] = 0; + } + } else + b = strndup(p, k); + + free(cgroup); + + if (!b) + return -ENOMEM; + + *unit = b; + return 0; + +}