]> git.ipfire.org Git - thirdparty/libcgroup.git/commitdiff
api.c: add support for empty cgroup v2 deletion
authorKamalesh Babulal <kamalesh.babulal@oracle.com>
Thu, 31 Mar 2022 12:21:55 +0000 (17:51 +0530)
committerTom Hromatka <tom.hromatka@oracle.com>
Fri, 1 Apr 2022 14:49:02 +0000 (08:49 -0600)
Add support to recognize empty cgroup v2 with no controllers attached to
it in cgroup_delete_cgroup_ext(), that gets called to remove a cgroup.

In the deletion path, cgroup_build_tasks_procs_path() builds the path
of the cgroup for re-assignment/movement of tasks from the cgroup that's
getting deleted, teach it to recognize the empty controller as cgroup
V2.

Fixes: https://github.com/libcgroup/libcgroup/issues/125
Signed-off-by: Kamalesh Babulal <kamalesh.babulal@oracle.com>
Signed-off-by: Tom Hromatka <tom.hromatka@oracle.com>
TJH: Fix a couple small typos in commit message

src/api.c

index a1fc4a0df10def137f1de9e4e30b454238e2a4c0..1c4eaa33a10dcfdf4c9cba76fa01a1562d2dfe47 100644 (file)
--- a/src/api.c
+++ b/src/api.c
@@ -3083,9 +3083,11 @@ int cgroup_delete_cgroup_ext(struct cgroup *cgroup, int flags)
 {
        int first_error = 0, first_errno = 0;
        char parent_path[FILENAME_MAX];
+       char *controller_name = NULL;
        FILE *parent_tasks = NULL;
        char *parent_name = NULL;
        int delete_group = 1;
+       int empty_cgroup = 0;
        int i, ret;
 
        if (!cgroup_initialized)
@@ -3098,19 +3100,31 @@ int cgroup_delete_cgroup_ext(struct cgroup *cgroup, int flags)
            && (flags & CGFLAG_DELETE_EMPTY_ONLY))
                return ECGINVAL;
 
+       if (cgroup->index == 0)
+               /* Valid empty cgroup v2 with not controllers added. */
+               empty_cgroup = 1;
+
        for (i = 0; i < cgroup->index; i++) {
                if (!cgroup_test_subsys_mounted(cgroup->controller[i]->name))
                        return ECGROUPSUBSYSNOTMOUNTED;
        }
 
-       /* Remove the group from all controllers. */
-       for (i = 0; i < cgroup->index; i++) {
+       /*
+        * Remove the group from all controllers and in the case of cgroup
+        * with no controllers, perform all actions of a single controller.
+        */
+       for (i = 0;
+            empty_cgroup > 0 || i < cgroup->index; i++, empty_cgroup--) {
+
                ret = 0;
+               controller_name = NULL;
+
+               if (cgroup->controller[i])
+                       controller_name = cgroup->controller[i]->name;
 
                /* Find parent, it can be different for each controller */
                if (!(flags & CGFLAG_DELETE_EMPTY_ONLY)) {
-                       ret = cgroup_find_parent(cgroup,
-                                                cgroup->controller[i]->name,
+                       ret = cgroup_find_parent(cgroup, controller_name,
                                                 &parent_name);
                        if (ret) {
                                if (first_error == 0) {
@@ -3147,7 +3161,7 @@ int cgroup_delete_cgroup_ext(struct cgroup *cgroup, int flags)
                        /* Tasks need to be moved, pre-open target tasks file */
                        ret = cgroup_build_tasks_procs_path(parent_path,
                                        sizeof(parent_path), parent_name,
-                                       cgroup->controller[i]->name);
+                                       controller_name);
                        if (ret != 0) {
                                if (first_error == 0)
                                        first_error = ECGFAIL;
@@ -3171,12 +3185,12 @@ int cgroup_delete_cgroup_ext(struct cgroup *cgroup, int flags)
                if (flags & CGFLAG_DELETE_RECURSIVE) {
                        ret = cg_delete_cgroup_controller_recursive(
                                        cgroup->name,
-                                       cgroup->controller[i]->name,
+                                       controller_name,
                                        parent_tasks, flags,
                                        delete_group);
                } else {
                        ret = cg_delete_cgroup_controller(cgroup->name,
-                                       cgroup->controller[i]->name,
+                                       controller_name,
                                        parent_tasks, flags);
                }
 
@@ -5940,6 +5954,11 @@ int cgroup_get_controller_version(const char * const controller,
        if (!version)
                return ECGINVAL;
 
+       if (!controller && strlen(cg_cgroup_v2_mount_path) > 0) {
+               *version = CGROUP_V2;
+               return 0;
+       }
+
        *version = CGROUP_UNK;
 
        for (i = 0; cg_mount_table[i].name[0] != '\0'; i++) {