When namespace is used, a group can have different parents for different controllers. cgroup_delete_cgroup_ext should reflect that.
Signed-off-by: Jan Safranek <jsafr...@redhat.com> --- src/api.c | 136 ++++++++++++++++++++++++++++++++++--------------------------- 1 files changed, 76 insertions(+), 60 deletions(-) diff --git a/src/api.c b/src/api.c index 1c6ca97..0b79bb6 100644 --- a/src/api.c +++ b/src/api.c @@ -1674,35 +1674,32 @@ static int cgroup_get_parent_name(struct cgroup *cgroup, char **parent) } /** - * Find the parent of the specified directory. It returns the parent (the - * parent is usually name/.. unless name is a mount point. It is assumed - * both the cgroup (and, therefore, parent) already exist, and will fail - * otherwise. + * Find the parent of the specified directory. It returns the parent in + * hierarchy of given controller (the parent is usually name/.. unless name is + * a mount point. It is assumed both the cgroup (and, therefore, parent) + * already exist, and will fail otherwise. + * + * When namespaces are used, a group can have different parents for different + * controllers. * * @param cgroup The cgroup + * @param controller The controller * @param parent Output, name of parent's group (if the group has parent) or * NULL, if the provided cgroup is the root group and has no parent. * Caller is responsible to free the returned string! * @return 0 on success, >0 on error. */ -static int cgroup_find_parent(struct cgroup *cgroup, char **parent) +static int cgroup_find_parent(struct cgroup *cgroup, char *controller, + char **parent) { char child_path[FILENAME_MAX]; char *parent_path = NULL; struct stat stat_child, stat_parent; - char *controller = NULL; int ret = 0; *parent = NULL; - /* if cgroup has no controllers attached, consider it unconfigured */ - if (cgroup->controller[0] == NULL) { - cgroup_dbg("cgroup_find_parent called on unconfigured group\n"); - return ECGFAIL; - } - pthread_rwlock_rdlock(&cg_mount_table_lock); - controller = cgroup->controller[0]->name; if (!cg_build_path_locked(cgroup->name, child_path, controller)) { pthread_rwlock_unlock(&cg_mount_table_lock); return ECGFAIL; @@ -2018,71 +2015,91 @@ int cgroup_delete_cgroup_ext(struct cgroup *cgroup, int flags) return ECGROUPSUBSYSNOTMOUNTED; } - if (!(flags & CGFLAG_DELETE_EMPTY_ONLY)) { - ret = cgroup_find_parent(cgroup, &parent_name); - if (ret) - return ret; - - if (parent_name == NULL) { - /* - * Root group is being deleted. - */ - if (flags & CGFLAG_DELETE_RECURSIVE) { - /* - * Move all tasks to the root group and do not - * delete it afterwards. - */ - parent_name = strdup("."); - if (parent_name == NULL) { - last_errno = errno; - return ECGOTHER; - } - delete_group = 0; - } else - /* - * TODO: should it succeed? - */ - return 0; - } - } - /* * Remove the group from all controllers. */ for (i = 0; i < cgroup->index; i++) { ret = 0; + /* find parent, it can be different for each controller */ + if (!(flags & CGFLAG_DELETE_EMPTY_ONLY)) { + ret = cgroup_find_parent(cgroup, + cgroup->controller[i]->name, + &parent_name); + if (ret) { + if (first_error == 0) { + first_errno = last_errno; + first_error = ret; + } + continue; + } + if (parent_name == NULL) { + /* + * Root group is being deleted. + */ + if (flags & CGFLAG_DELETE_RECURSIVE) { + /* + * Move all tasks to the root group and + * do not delete it afterwards. + */ + parent_name = strdup("."); + if (parent_name == NULL) { + if (first_error == 0) { + first_errno = errno; + first_error = ECGOTHER; + } + continue; + } + delete_group = 0; + } else + /* + * root group is being deleted in non- + * recursive mode + */ + continue; + } + } + if (parent_name) { /* tasks need to be moved, pre-open target tasks file */ if (!cg_build_path(parent_name, parent_path, - cgroup->controller[i]->name)) + cgroup->controller[i]->name)) { + if (first_error == 0) + first_error = ECGFAIL; + free(parent_name); continue; - + } strncat(parent_path, "/tasks", sizeof(parent_path) - strlen(parent_path)); parent_tasks = fopen(parent_path, "we"); if (!parent_tasks) { - last_errno = errno; - ret = ECGOTHER; + if (first_error == 0) { + first_errno = errno; + first_error = ECGOTHER; + } + free(parent_name); + continue; } } - if (parent_tasks || !parent_name) { - if (flags & CGFLAG_DELETE_RECURSIVE) { - ret = cg_delete_cgroup_controller_recursive( - cgroup->name, - cgroup->controller[i]->name, - parent_tasks, flags, - delete_group); - } else { - ret = cg_delete_cgroup_controller(cgroup->name, - cgroup->controller[i]->name, - parent_tasks, flags); - } - if (parent_tasks) - fclose(parent_tasks); + if (flags & CGFLAG_DELETE_RECURSIVE) { + ret = cg_delete_cgroup_controller_recursive( + cgroup->name, + cgroup->controller[i]->name, + parent_tasks, flags, + delete_group); + } else { + ret = cg_delete_cgroup_controller(cgroup->name, + cgroup->controller[i]->name, + parent_tasks, flags); } + if (parent_tasks) { + fclose(parent_tasks); + parent_tasks = NULL; + } + free(parent_name); + parent_name = NULL; /* * If any of the controller delete fails, remember the first * error code, but continue with next controller and try remove @@ -2101,7 +2118,6 @@ int cgroup_delete_cgroup_ext(struct cgroup *cgroup, int flags) if (first_errno != 0) last_errno = first_errno; - free(parent_name); return first_error; } ------------------------------------------------------------------------------ All of the data generated in your IT infrastructure is seriously valuable. Why? It contains a definitive record of application performance, security threats, fraudulent activity, and more. Splunk takes this data and makes sense of it. IT sense. And common sense. http://p.sf.net/sfu/splunk-d2dcopy2 _______________________________________________ Libcg-devel mailing list Libcg-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libcg-devel