From 539d07eae4d5963c3bddd821f7c5f02db2476741 Mon Sep 17 00:00:00 2001 From: Kamalesh Babulal Date: Sun, 15 Oct 2023 14:13:56 +0530 Subject: [PATCH] api.c: enable controller in the root_cgroup.subtree_file 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 Signed-off-by: Tom Hromatka --- src/api.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/api.c b/src/api.c index 93964e2d..e8b97523 100644 --- 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) { -- 2.47.2