diff options
author | Lennart Poettering <lennart@poettering.net> | 2013-06-20 03:45:08 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2013-06-20 03:49:59 +0200 |
commit | 9444b1f20e311f073864d81e913bd4f32fe95cfd (patch) | |
tree | 7b4752c690729df0acec75c9eb2382026bbf6899 /src/shared/cgroup-util.c | |
parent | 77f40f165cc60a1d6b8a3503e4b7e46814d5935e (diff) |
logind: add infrastructure to keep track of machines, and move to slices
- This changes all logind cgroup objects to use slice objects rather
than fixed croup locations.
- logind can now collect minimal information about running
VMs/containers. As fixed cgroup locations can no longer be used we
need an entity that keeps track of machine cgroups in whatever slice
they might be located. Since logind already keeps track of users,
sessions and seats this is a trivial addition.
- nspawn will now register with logind and pass various bits of metadata
along. A new option "--slice=" has been added to place the container
in a specific slice.
- loginctl gained commands to list, introspect and terminate machines.
- user.slice and machine.slice will now be pulled in by logind.service,
since only logind.service requires this slice.
Diffstat (limited to 'src/shared/cgroup-util.c')
-rw-r--r-- | src/shared/cgroup-util.c | 220 |
1 files changed, 97 insertions, 123 deletions
diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c index 4f58affe38..05d026a587 100644 --- a/src/shared/cgroup-util.c +++ b/src/shared/cgroup-util.c @@ -38,6 +38,7 @@ #include "strv.h" #include "unit-name.h" #include "fileio.h" +#include "special.h" int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) { _cleanup_free_ char *fs = NULL; @@ -470,19 +471,19 @@ 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 = NULL; - if (controller) { - if (path && suffix) + if (!isempty(controller)) { + if (!isempty(path) && !isempty(suffix)) t = strjoin("/sys/fs/cgroup/", controller, "/", path, "/", suffix, NULL); - else if (path) + else if (!isempty(path)) t = strjoin("/sys/fs/cgroup/", controller, "/", path, NULL); - else if (suffix) + else if (!isempty(suffix)) t = strjoin("/sys/fs/cgroup/", controller, "/", suffix, NULL); else t = strappend("/sys/fs/cgroup/", controller); } else { - if (path && suffix) + if (!isempty(path) && !isempty(suffix)) t = strjoin(path, "/", suffix, NULL); - else if (path) + else if (!isempty(path)) t = strdup(path); else return -EINVAL; @@ -1091,96 +1092,20 @@ int cg_mangle_path(const char *path, char **result) { return cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result); } -int cg_get_system_path(char **path) { - char *p; - int r; - - assert(path); - - r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &p); - if (r < 0) { - p = strdup("/system"); - if (!p) - return -ENOMEM; - } - - if (endswith(p, "/system")) - *path = p; - else { - char *q; - - q = strappend(p, "/system"); - free(p); - if (!q) - return -ENOMEM; - - *path = q; - } - - return 0; -} - int cg_get_root_path(char **path) { - char *root, *e; + char *p, *e; int r; assert(path); - r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &root); + r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &p); if (r < 0) return r; - e = endswith(root, "/system"); - if (e == root) - e[1] = 0; - else if (e) + e = endswith(p, "/" SPECIAL_SYSTEM_SLICE); + if (e) *e = 0; - *path = root; - return 0; -} - -int cg_get_user_path(char **path) { - _cleanup_free_ char *root = NULL; - char *p; - - assert(path); - - /* Figure out the place to put user cgroups below. We use the - * same as PID 1 has but with the "/system" suffix replaced by - * "/user" */ - - if (cg_get_root_path(&root) < 0 || streq(root, "/")) - p = strdup("/user"); - else - p = strappend(root, "/user"); - - if (!p) - return -ENOMEM; - - *path = p; - return 0; -} - -int cg_get_machine_path(const char *machine, char **path) { - _cleanup_free_ char *root = NULL, *escaped = NULL; - char *p; - - assert(path); - - if (machine) { - const char *name = strappenda(machine, ".nspawn"); - - escaped = cg_escape(name); - if (!escaped) - return -ENOMEM; - } - - p = strjoin(cg_get_root_path(&root) >= 0 && !streq(root, "/") ? root : "", - "/machine", machine ? "/" : "", machine ? escaped : "", NULL); - if (!p) - return -ENOMEM; - *path = p; return 0; } @@ -1301,15 +1226,29 @@ int cg_path_decode_unit(const char *cgroup, char **unit){ return 0; } +static const char *skip_slices(const char *p) { + size_t n; + + /* Skips over all slice assignments */ + + for (;;) { + p += strspn(p, "/"); + + n = strcspn(p, "/"); + if (n <= 6 || memcmp(p + n - 6, ".slice", 6) != 0) + return p; + + p += n; + } +} + int cg_path_get_unit(const char *path, char **unit) { const char *e; assert(path); assert(unit); - e = path_startswith(path, "/system/"); - if (!e) - return -ENOENT; + e = skip_slices(path); return cg_path_decode_unit(e, unit); } @@ -1327,15 +1266,55 @@ int cg_pid_get_unit(pid_t pid, char **unit) { return cg_path_get_unit(cgroup, unit); } -_pure_ static const char *skip_label(const char *e) { - assert(e); +static const char *skip_user(const char *p) { + size_t n; - e = strchr(e, '/'); - if (!e) + assert(p); + + p += strspn(p, "/"); + + n = strcspn(p, "/"); + if (n <= 5 || memcmp(p + n - 5, ".user", 5) != 0) + return p; + + p += n; + p += strspn(p, "/"); + + return p; +} + +static const char *skip_session(const char *p) { + size_t n; + + assert(p); + + p += strspn(p, "/"); + + n = strcspn(p, "/"); + if (n <= 8 || memcmp(p + n - 8, ".session", 8) != 0) return NULL; - e += strspn(e, "/"); - return e; + p += n; + p += strspn(p, "/"); + + return p; +} + +static const char *skip_systemd_label(const char *p) { + size_t n; + + assert(p); + + p += strspn(p, "/"); + + n = strcspn(p, "/"); + if (n < 8 || memcmp(p, "systemd-", 8) != 0) + return p; + + p += n; + p += strspn(p, "/"); + + return p; } int cg_path_get_user_unit(const char *path, char **unit) { @@ -1348,24 +1327,19 @@ int cg_path_get_user_unit(const char *path, char **unit) { * cgroups might have arbitrary child cgroups and we shouldn't get * confused by those */ - e = path_startswith(path, "/user/"); - if (!e) - return -ENOENT; + /* Skip slices, if there are any */ + e = skip_slices(path); - /* Skip the user name */ - e = skip_label(e); - if (!e) - return -ENOENT; + /* Skip the user name, if there is one */ + e = skip_user(e); - /* Skip the session ID */ - e = skip_label(e); + /* Skip the session ID, require that there is one */ + e = skip_session(e); if (!e) return -ENOENT; - /* Skip the systemd cgroup */ - e = skip_label(e); - if (!e) - return -ENOENT; + /* Skip the systemd cgroup, if there is one */ + e = skip_systemd_label(e); return cg_path_decode_unit(e, unit); } @@ -1384,23 +1358,27 @@ 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; + const char *e, *n, *x; char *s, *r; assert(path); assert(machine); - e = path_startswith(path, "/machine/"); - if (!e) - return -ENOENT; + /* 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 = endswith(s, ".machine"); + if (!x) + return -ENOENT; - r = strdup(cg_unescape(s)); + r = strndup(s, x - s); if (!r) return -ENOMEM; @@ -1428,14 +1406,11 @@ int cg_path_get_session(const char *path, char **session) { assert(path); assert(session); - e = path_startswith(path, "/user/"); - if (!e) - return -ENOENT; + /* Skip slices, if there are any */ + e = skip_slices(path); - /* Skip the user name */ - e = skip_label(e); - if (!e) - return -ENOENT; + /* Skip the user name, if there is one */ + e = skip_user(e); n = strchrnul(e, '/'); if (n - e < 8) @@ -1471,9 +1446,8 @@ int cg_path_get_owner_uid(const char *path, uid_t *uid) { assert(path); assert(uid); - e = path_startswith(path, "/user/"); - if (!e) - return -ENOENT; + /* Skip slices, if there are any */ + e = skip_slices(path); n = strchrnul(e, '/'); if (n - e < 5) |