X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=cgroup.c;h=301fc949dada5c8fa590ee90723cc7b7716ba9a3;hp=9e1b0de379a2f4d29de4aeef5753461eba0ed2e8;hb=e3d1855bb991f7b118b77e6a2520eb4049cf5438;hpb=58783cdaec345e9a34c2ed2218fe4670d1d0dce5 diff --git a/cgroup.c b/cgroup.c index 9e1b0de37..301fc949d 100644 --- a/cgroup.c +++ b/cgroup.c @@ -118,17 +118,15 @@ void cgroup_bonding_free(CGroupBonding *b) { hashmap_remove(b->unit->meta.manager->cgroup_bondings, b->path); } - free(b->controller); - free(b->path); - if (b->cgroup) { - - if (b->only_us && b->clean_up) - cgroup_delete_cgroup(b->cgroup, true); + if (b->only_us && b->clean_up && cgroup_bonding_is_empty(b) > 0) + cgroup_delete_cgroup_ext(b->cgroup, true); cgroup_free(&b->cgroup); } + free(b->controller); + free(b->path); free(b); } @@ -174,10 +172,14 @@ int cgroup_bonding_kill(CGroupBonding *b, int sig) { int r; Set *s; bool done; + bool killed = false; assert(b); assert(sig > 0); + if (!b->only_us) + return -EAGAIN; + if (!(s = set_new(trivial_hash_func, trivial_compare_func))) return -ENOMEM; @@ -208,6 +210,7 @@ int cgroup_bonding_kill(CGroupBonding *b, int sig) { break; } + killed = true; done = false; if ((r = set_put(s, INT_TO_PTR(pid))) < 0) @@ -235,20 +238,29 @@ int cgroup_bonding_kill(CGroupBonding *b, int sig) { } while (!done && r >= 0); set_free(s); - return r; + + if (r < 0) + return r; + + return killed ? 0 : -ESRCH; } int cgroup_bonding_kill_list(CGroupBonding *first, int sig) { CGroupBonding *b; + int r = -EAGAIN; LIST_FOREACH(by_unit, b, first) { - int r; + if ((r = cgroup_bonding_kill(b, sig)) < 0) { + if (r == -EAGAIN || -ESRCH) + continue; - if ((r = cgroup_bonding_kill(b, sig)) < 0) return r; + } + + return 0; } - return 0; + return r; } /* Returns 1 if the group is empty, 0 if it is not, -EAGAIN if we @@ -400,6 +412,7 @@ int manager_setup_cgroup(Manager *m) { char *mp, *cp; int r; pid_t pid; + char suffix[32]; assert(m); @@ -422,36 +435,48 @@ int manager_setup_cgroup(Manager *m) { return translate_error(r, errno); } + snprintf(suffix, sizeof(suffix), "/systemd-%u", (unsigned) pid); + char_array_0(suffix); + free(m->cgroup_hierarchy); - m->cgroup_hierarchy = NULL; - if (asprintf(&m->cgroup_hierarchy, "%s/systemd-%llu", strcmp(cp, "/") == 0 ? "" : cp, (unsigned long long) pid) < 0) { + + if (endswith(cp, suffix)) + /* We probably got reexecuted and can continue to use our root cgroup */ + m->cgroup_hierarchy = cp; + else { + /* We need a new root cgroup */ + + m->cgroup_hierarchy = NULL; + r = asprintf(&m->cgroup_hierarchy, "%s%s", streq(cp, "/") ? "" : cp, suffix); free(cp); - free(mp); - return -ENOMEM; + + if (r < 0) { + free(mp); + return -ENOMEM; + } } - log_info("Using cgroup controller <%s>, hierarchy mounted at <%s>, using root group <%s>.", - m->cgroup_controller, - mp, - m->cgroup_hierarchy); + log_debug("Using cgroup controller <%s>, hierarchy mounted at <%s>, using root group <%s>.", + m->cgroup_controller, + mp, + m->cgroup_hierarchy); if ((r = install_release_agent(m, mp)) < 0) log_warning("Failed to install release agent, ignoring: %s", strerror(-r)); else - log_info("Installed release agent, or already installed."); + log_debug("Installed release agent, or already installed."); free(mp); - free(cp); if ((r = create_hierarchy_cgroup(m)) < 0) log_error("Failed to create root cgroup hierarchy: %s", strerror(-r)); else - log_info("Created root group."); + log_debug("Created root group."); return r; } -int manager_shutdown_cgroup(Manager *m) { +int manager_shutdown_cgroup(Manager *m, bool delete) { struct cgroup *cg; int r; @@ -468,11 +493,10 @@ int manager_shutdown_cgroup(Manager *m) { goto finish; } - if ((r = cgroup_delete_cgroup_ext(cg, CGFLAG_DELETE_IGNORE_MIGRATION|CGFLAG_DELETE_RECURSIVE)) != 0) { - log_error("Failed to delete cgroup hierarchy group: %s", cgroup_strerror(r)); - r = translate_error(r, errno); - goto finish; - } + /* Often enough we won't be able to delete the cgroup we + * ourselves are in, hence ignore all errors here */ + if (delete) + cgroup_delete_cgroup_ext(cg, CGFLAG_DELETE_IGNORE_MIGRATION|CGFLAG_DELETE_RECURSIVE); r = 0; finish: @@ -524,3 +548,14 @@ CGroupBonding *cgroup_bonding_find_list(CGroupBonding *first, const char *contro return NULL; } + +char *cgroup_bonding_to_string(CGroupBonding *b) { + char *r; + + assert(b); + + if (asprintf(&r, "%s:%s", b->controller, b->path) < 0) + return NULL; + + return r; +}