From: Lennart Poettering Date: Fri, 3 Feb 2012 04:25:31 +0000 (+0100) Subject: cgroup: when getting cgroup empty notifications, always search up the tree X-Git-Tag: v40~3 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=acb14d318b84bda00d1e666d7dab6794d5bbeb3f cgroup: when getting cgroup empty notifications, always search up the tree --- diff --git a/TODO b/TODO index 74a36a1df..c2113f881 100644 --- a/TODO +++ b/TODO @@ -31,7 +31,7 @@ Features: * write RPM spec macros for presets -* write man pages for systemd-cgtop, systemd-cat +* write man pages for systemd-cat * journal: write man pages for API @@ -73,8 +73,6 @@ Features: * move to LGPL2+ -* logind: selinux is borked... - * logind: allow showing logout dialog from system * document that %% can be used to write % in a string that is specifier extended @@ -164,8 +162,6 @@ Features: * GC unreferenced jobs (such as .device jobs) -* cgroup_notify_empty(): recursively check groups up the tree, too - * when failing to start a service due to ratelimiting, try again later, if restart=always is set * write blog stories about: @@ -175,6 +171,7 @@ Features: - remote access - how to pass throw-away units to systemd, or dynamically change properties of existing units - how to integrate cgconfig and suchlike with systemd + - resource control in systemd * allow port=0 in .socket units diff --git a/src/cgroup.c b/src/cgroup.c index 9aff02e7b..182dd59ee 100644 --- a/src/cgroup.c +++ b/src/cgroup.c @@ -355,15 +355,55 @@ void manager_shutdown_cgroup(Manager *m, bool delete) { m->cgroup_hierarchy = NULL; } +int cgroup_bonding_get(Manager *m, const char *cgroup, CGroupBonding **bonding) { + CGroupBonding *b; + char *p; + + assert(m); + assert(cgroup); + assert(bonding); + + b = hashmap_get(m->cgroup_bondings, cgroup); + if (!b) { + *bonding = b; + return 1; + } + + p = strdup(cgroup); + if (!p) + return -ENOMEM; + + for (;;) { + char *e; + + e = strrchr(p, '/'); + if (!e || e == p) { + free(p); + *bonding = NULL; + return 0; + } + + *e = 0; + + b = hashmap_get(m->cgroup_bondings, p); + if (b) { + free(p); + *bonding = b; + return 1; + } + } +} + int cgroup_notify_empty(Manager *m, const char *group) { CGroupBonding *l, *b; + int r; assert(m); assert(group); - l = hashmap_get(m->cgroup_bondings, group); - if (!l) - return 0; + r = cgroup_bonding_get(m, group, &l); + if (r <= 0) + return r; LIST_FOREACH(by_path, b, l) { int t; diff --git a/src/cgroup.h b/src/cgroup.h index db4feb916..5faa7dc0f 100644 --- a/src/cgroup.h +++ b/src/cgroup.h @@ -86,6 +86,7 @@ pid_t cgroup_bonding_search_main_pid_list(CGroupBonding *b); int manager_setup_cgroup(Manager *m); void manager_shutdown_cgroup(Manager *m, bool delete); +int cgroup_bonding_get(Manager *m, const char *cgroup, CGroupBonding **bonding); int cgroup_notify_empty(Manager *m, const char *group); Unit* cgroup_unit_by_pid(Manager *m, pid_t pid); diff --git a/src/login/logind.c b/src/login/logind.c index 8997b4689..7fd6515ff 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -782,12 +782,19 @@ finish: } int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) { + Session *s; char *p; assert(m); assert(cgroup); assert(session); + s = hashmap_get(m->cgroups, cgroup); + if (s) { + *session = s; + return 1; + } + p = strdup(cgroup); if (!p) { log_error("Out of memory."); @@ -795,24 +802,23 @@ int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **sess } for (;;) { - Session *s; char *e; - if (isempty(p) || streq(p, "/")) { + e = strrchr(p, '/'); + if (!e || e == p) { free(p); *session = NULL; return 0; } + *e = 0; + s = hashmap_get(m->cgroups, p); if (s) { free(p); *session = s; return 1; } - - assert_se(e = strrchr(p, '/')); - *e = 0; } }