]> git.ipfire.org Git - thirdparty/libcgroup.git/commitdiff
api.c: enable controller in the root_cgroup.subtree_file
authorKamalesh Babulal <kamalesh.babulal@oracle.com>
Sun, 15 Oct 2023 08:43:56 +0000 (14:13 +0530)
committerTom Hromatka <tom.hromatka@oracle.com>
Wed, 25 Oct 2023 20:23:20 +0000 (14:23 -0600)
systemd by default only enables cpu, cpuset, io, memory, and pids
controller the root_cgroup.subtree_control. Trying to enable other
controllers (hugetlb and misc) in a nested cgroups create scenario,
will fail because they are not, enabled the controller in the
root_cgroup.subtree_control file.

$ sudo cgcreate -ghugetlb:foo/bar
Error: Failed to delete foo/bar: No such file or directory
cgcreate: can't create cgroup foo/bar: No such file or directory

Fix this by enabling the controller in the root_cgroup.subtree_control
file unconditionally for all controllers, if not already enabled, while
calling cgroupv2_subtree_control_recursive() to enable the controller
in the given cgroup and its descendants. Checking and enabling every
controller unconditionally should work in the future, in case systemd
disables some other controllers too.

Fixes: https://github.com/libcgroup/libcgroup/issues/405
Signed-off-by: Kamalesh Babulal <kamalesh.babulal@oracle.com>
Signed-off-by: Tom Hromatka <tom.hromatka@oracle.com>
src/api.c

index 93964e2dbc5f7b9bd7ee85cf3b80c43817ad88c5..e8b9752367bff8887f899a3e9d79029bde585b03 100644 (file)
--- a/src/api.c
+++ b/src/api.c
@@ -2534,6 +2534,36 @@ out:
        return error;
 }
 
+/*
+ * Test if the controller is enabled in the root_cgrp.subtree_control file
+ * and enable the controller, if not enabled.
+ */
+static int test_and_set_ctrl_mnt_path(const char * const mount_path, const char * const ctrl_name)
+{
+       bool enabled;
+       int ret;
+
+       /* return if the controller is enabled */
+       ret = cgroupv2_get_subtree_control(mount_path, ctrl_name, &enabled);
+       if (ret == ECGOTHER)
+               return ret;
+
+       if (enabled == true)
+               return 0;
+
+       /* check if the controller is available is controllers file */
+       ret = cgroupv2_get_controllers(mount_path, ctrl_name, &enabled);
+       if (ret == ECGOTHER || ret == ECGROUPNOTMOUNTED)
+               return ret;
+
+       /* enable the controller in the subtree_control file */
+       ret = cgroupv2_subtree_control(mount_path, ctrl_name, 1);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
 /**
  * Recursively enable/disable a controller in the cgv2 subtree_control file
  *
@@ -2571,6 +2601,22 @@ STATIC int cgroupv2_subtree_control_recursive(char *path, const char *ctrl_name,
        mount_len = strlen(cg_mount_table[i].mount.path);
        path_copy[mount_len] = '\0';
 
+       /*
+        * systemd by default only enables cpu, cpuset, io, memory, and pids
+        * controller in the root_cgroup.subtree_control. Trying to enable
+        * hugetlb and misc controller in a nested cgroups, will fail
+        * because they are not, enabled the controller in the root_cgroup.
+        * i.e. # cgcreate -ghugetlb:foo/bar
+        *
+        * check if the controller is enabled in the
+        * root_cgroup.subtree_control file and if not enable it. Let's
+        * check for all controllers, so that it accommodates other
+        * controllers systemd decides to disable by default in the future.
+        */
+       error = test_and_set_ctrl_mnt_path(path_copy, ctrl_name);
+       if (error)
+               goto out;
+
        tmp_path = strtok_r(&path[mount_len], "/", &stok_buff);
        do {
                if (tmp_path) {