X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fshared%2Fcgroup-util.c;h=c1c4d409ae5ee6bcc30d5d743473417861dbc6e4;hp=2c2ffc589879ead8b7f04c2cf31bcff833d428cb;hb=f7f628b5db770feb8b18990436baefaec55c460b;hpb=e9174f29c7e3ee45137537b126458718913a3ec5 diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c index 2c2ffc589..c1c4d409a 100644 --- a/src/shared/cgroup-util.c +++ b/src/shared/cgroup-util.c @@ -194,12 +194,12 @@ int cg_kill(const char *controller, const char *path, int sig, bool sigcont, boo if (kill(pid, sig) < 0) { if (ret >= 0 && errno != ESRCH) ret = -errno; - } else if (ret == 0) { - + } else { if (sigcont) kill(pid, SIGCONT); - ret = 1; + if (ret == 0) + ret = 1; } done = false; @@ -472,15 +472,13 @@ static int join_path(const char *controller, const char *path, const char *suffi if (!t) return -ENOMEM; - path_kill_slashes(t); - - *fs = t; + *fs = path_kill_slashes(t); return 0; } int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) { const char *p; - static __thread bool good = false; + static thread_local bool good = false; assert(fs); @@ -509,7 +507,7 @@ static int check_hierarchy(const char *p) { assert(p); /* Check if this controller actually really exists */ - cc = alloca(sizeof("/sys/fs/cgroup/") + strlen(p)); + cc = alloca(strlen("/sys/fs/cgroup/") + strlen(p) + 1); strcpy(stpcpy(cc, "/sys/fs/cgroup/"), p); if (access(cc, F_OK) < 0) return -errno; @@ -643,7 +641,7 @@ int cg_attach(const char *controller, const char *path, pid_t pid) { if (pid == 0) pid = getpid(); - snprintf(c, sizeof(c), "%lu\n", (unsigned long) pid); + snprintf(c, sizeof(c), PID_FMT"\n", pid); return write_string_file(fs, c); } @@ -746,10 +744,7 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) { } else controller = SYSTEMD_CGROUP_CONTROLLER; - if (pid == 0) - fs = "/proc/self/cgroup"; - else - fs = procfs_file_alloca(pid, "cgroup"); + fs = procfs_file_alloca(pid, "cgroup"); f = fopen(fs, "re"); if (!f) @@ -960,8 +955,7 @@ int cg_split_spec(const char *spec, char **controller, char **path) { if (!t) return -ENOMEM; - path_kill_slashes(t); - *path = t; + *path = path_kill_slashes(t); } if (controller) @@ -1044,19 +1038,18 @@ int cg_mangle_path(const char *path, char **result) { assert(path); assert(result); - /* First check if it already is a filesystem path */ + /* First, check if it already is a filesystem path */ if (path_startswith(path, "/sys/fs/cgroup")) { t = strdup(path); if (!t) return -ENOMEM; - path_kill_slashes(t); - *result = t; + *result = path_kill_slashes(t); return 0; } - /* Otherwise treat it as cg spec */ + /* Otherwise, treat it as cg spec */ r = cg_split_spec(path, &c, &p); if (r < 0) return r; @@ -1082,42 +1075,62 @@ int cg_get_root_path(char **path) { return 0; } -int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) { - _cleanup_free_ char *cg_root = NULL; - char *cg_process, *p; +int cg_shift_path(const char *cgroup, const char *root, const char **shifted) { + _cleanup_free_ char *rt = NULL; + char *p; int r; - assert(pid >= 0); assert(cgroup); + assert(shifted); if (!root) { /* If the root was specified let's use that, otherwise * let's determine it from PID 1 */ - r = cg_get_root_path(&cg_root); + r = cg_get_root_path(&rt); if (r < 0) return r; - root = cg_root; + root = rt; } - r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cg_process); + p = path_startswith(cgroup, root); + if (p) + *shifted = p - 1; + else + *shifted = cgroup; + + return 0; +} + +int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) { + _cleanup_free_ char *raw = NULL; + const char *c; + int r; + + assert(pid >= 0); + assert(cgroup); + + r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &raw); if (r < 0) return r; - p = path_startswith(cg_process, root); - if (p) { - char *c; + r = cg_shift_path(raw, root, &c); + if (r < 0) + return r; - c = strdup(p - 1); - free(cg_process); + if (c == raw) { + *cgroup = raw; + raw = NULL; + } else { + char *n; - if (!c) + n = strdup(c); + if (!n) return -ENOMEM; - *cgroup = c; - } else - *cgroup = cg_process; + *cgroup = n; + } return 0; } @@ -1132,7 +1145,7 @@ int cg_path_decode_unit(const char *cgroup, char **unit){ c = strndupa(cgroup, e - cgroup); c = cg_unescape(c); - if (!unit_name_is_valid(c, false)) + if (!unit_name_is_valid(c, TEMPLATE_INVALID)) return -EINVAL; s = strdup(c); @@ -1183,6 +1196,9 @@ int cg_pid_get_unit(pid_t pid, char **unit) { return cg_path_get_unit(cgroup, unit); } +/** + * Skip session-*.scope, but require it to be there. + */ static const char *skip_session(const char *p) { size_t n; @@ -1191,7 +1207,27 @@ static const char *skip_session(const char *p) { p += strspn(p, "/"); n = strcspn(p, "/"); - if (n <= 12 || memcmp(p, "session-", 8) != 0 || memcmp(p + n - 6, ".scope", 6) != 0) + if (n < strlen("session-x.scope") || memcmp(p, "session-", 8) != 0 || memcmp(p + n - 6, ".scope", 6) != 0) + return NULL; + + p += n; + p += strspn(p, "/"); + + return p; +} + +/** + * Skip user@*.service, but require it to be there. + */ +static const char *skip_user_manager(const char *p) { + size_t n; + + assert(p); + + p += strspn(p, "/"); + + n = strcspn(p, "/"); + if (n < strlen("user@x.service") || memcmp(p, "user@", 5) != 0 || memcmp(p + n - 8, ".service", 8) != 0) return NULL; p += n; @@ -1201,7 +1237,7 @@ static const char *skip_session(const char *p) { } int cg_path_get_user_unit(const char *path, char **unit) { - const char *e; + const char *e, *t; assert(path); assert(unit); @@ -1213,13 +1249,17 @@ int cg_path_get_user_unit(const char *path, char **unit) { /* Skip slices, if there are any */ e = skip_slices(path); - /* Skip the session scope, require that there is one */ - e = skip_session(e); - if (!e) - return -ENOENT; - - /* And skip more slices */ - e = skip_slices(e); + /* Skip the session scope... */ + t = skip_session(e); + if (t) + /* ... and skip more slices if there's one */ + e = skip_slices(t); + else { + /* ... or require a user manager unit to be there */ + e = skip_user_manager(e); + if (!e) + return -ENOENT; + } return cg_path_decode_unit(e, unit); } @@ -1238,39 +1278,18 @@ int cg_pid_get_user_unit(pid_t pid, char **unit) { } int cg_path_get_machine_name(const char *path, char **machine) { - const char *e, *n, *x; - char *s, *r; - size_t l; - - assert(path); - assert(machine); - - /* Skip slices, if there are any */ - e = skip_slices(path); - - n = strchrnul(e, '/'); - if (e == n) - return -ENOENT; - - s = strndupa(e, n - e); - s = cg_unescape(s); - - x = startswith(s, "machine-"); - if (!x) - return -ENOENT; - if (!endswith(x, ".scope")) - return -ENOENT; + _cleanup_free_ char *u = NULL, *sl = NULL; + int r; - l = strlen(x); - if (l <= 6) - return -ENOENT; + r = cg_path_get_unit(path, &u); + if (r < 0) + return r; - r = strndup(x, l - 6); - if (!r) + sl = strjoin("/run/systemd/machines/unit:", u, NULL); + if (!sl) return -ENOMEM; - *machine = r; - return 0; + return readlink_malloc(sl, machine); } int cg_pid_get_machine_name(pid_t pid, char **machine) { @@ -1288,11 +1307,10 @@ int cg_pid_get_machine_name(pid_t pid, char **machine) { int cg_path_get_session(const char *path, char **session) { const char *e, *n, *x; - char *s, *r; + char *s; size_t l; assert(path); - assert(session); /* Skip slices, if there are any */ e = skip_slices(path); @@ -1314,11 +1332,16 @@ int cg_path_get_session(const char *path, char **session) { if (l <= 6) return -ENOENT; - r = strndup(x, l - 6); - if (!r) - return -ENOMEM; + if (session) { + char *r; + + r = strndup(x, l - 6); + if (!r) + return -ENOMEM; + + *session = r; + } - *session = r; return 0; } @@ -1326,8 +1349,6 @@ int cg_pid_get_session(pid_t pid, char **session) { _cleanup_free_ char *cgroup = NULL; int r; - assert(session); - r = cg_pid_get_path_shifted(pid, NULL, &cgroup); if (r < 0) return r; @@ -1519,7 +1540,7 @@ int cg_slice_to_path(const char *unit, char **ret) { assert(unit); assert(ret); - if (!unit_name_is_valid(unit, false)) + if (!unit_name_is_valid(unit, TEMPLATE_INVALID)) return -EINVAL; if (!endswith(unit, ".slice")) @@ -1536,7 +1557,7 @@ int cg_slice_to_path(const char *unit, char **ret) { strcpy(stpncpy(n, p, dash - p), ".slice"); - if (!unit_name_is_valid(n, false)) + if (!unit_name_is_valid(n, TEMPLATE_INVALID)) return -EINVAL; escaped = cg_escape(n); @@ -1643,7 +1664,7 @@ int cg_attach_many_everywhere(CGroupControllerMask supported, const char *path, return r; } -int cg_migrate_everywhere(CGroupControllerMask supported, const char *from, const char *to) { +int cg_migrate_everywhere(CGroupControllerMask supported, const char *from, const char *to, cg_migrate_callback_t to_callback, void *userdata) { CGroupControllerMask bit = 1; const char *n; int r; @@ -1655,8 +1676,17 @@ int cg_migrate_everywhere(CGroupControllerMask supported, const char *from, cons } NULSTR_FOREACH(n, mask_names) { - if (supported & bit) - cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, n, to, false, false); + if (supported & bit) { + const char *p = NULL; + + if (to_callback) + p = to_callback(bit, userdata); + + if (!p) + p = to; + + cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, n, p, false, false); + } bit <<= 1; }