This commit adds the function cgroupv2_controller_enabled(). Given a controller name and a cgroup name, this function determines if the controller is enabled for this cgroup by reading the parent cgroup's cgroup.subtree_control file and looking for the requested controller.
This check is required to ensure that the cgexec and cgclassify operations will succeed. And with this commit, cgexec and cgclassify work on both cgroup v1 and cgroup v2 hierarchies. Signed-off-by: Tom Hromatka <tom.hroma...@oracle.com> --- src/api.c | 63 +++++++++++++++++++++++++++++++++++++++- src/libcgroup-internal.h | 4 +++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/src/api.c b/src/api.c index 88042f95a51c..1377898912e8 100644 --- a/src/api.c +++ b/src/api.c @@ -127,6 +127,10 @@ static const char * const cgroup_ignored_tasks_files[] = { "tasks", NULL }; static int cg_get_cgroups_from_proc_cgroups(pid_t pid, char *cgroup_list[], char *controller_list[], int list_len); + +static int cgroupv2_get_subtree_control(const char *path, + const char *ctrl_name, + bool * const enabled); #endif static int cg_chown(const char *filename, uid_t owner, gid_t group) @@ -1541,6 +1545,53 @@ error: return err; } +STATIC int cgroupv2_controller_enabled(const char * const cg_name, + const char * const ctrl_name) +{ + char path[FILENAME_MAX] = {0}; + char *parent = NULL, *dname; + enum cg_version_t version; + bool enabled; + int error; + + error = cgroup_get_controller_version(ctrl_name, &version); + if (error) + return error; + + if (version != CGROUP_V2) + return 0; + + if (strncmp(cg_name, "/", strlen(cg_name)) == 0) + /* + * The root cgroup has been requested. All version 2 + * controllers are enabled on the root cgroup + */ + return 0; + + if (!cg_build_path(cg_name, path, ctrl_name)) + goto err; + + parent = strdup(path); + if (!parent) { + error = ECGOTHER; + goto err; + } + + dname = dirname(parent); + + error = cgroupv2_get_subtree_control(dname, ctrl_name, &enabled); + if (error) + goto err; + + if (enabled) + error = 0; +err: + if (parent) + free(parent); + + return error; +} + static int __cgroup_attach_task_pid(char *path, pid_t tid) { int ret = 0; @@ -1592,7 +1643,7 @@ err: */ int cgroup_attach_task_pid(struct cgroup *cgroup, pid_t tid) { - char path[FILENAME_MAX]; + char path[FILENAME_MAX] = {0}; int i, ret = 0; if (!cgroup_initialized) { @@ -1603,6 +1654,11 @@ int cgroup_attach_task_pid(struct cgroup *cgroup, pid_t tid) pthread_rwlock_rdlock(&cg_mount_table_lock); for (i = 0; i < CG_CONTROLLER_MAX && cg_mount_table[i].name[0] != '\0'; i++) { + ret = cgroupv2_controller_enabled(cgroup->name, + cgroup->controller[i]->name); + if (ret) + return ret; + ret = cgroup_build_tasks_procs_path(path, sizeof(path), cgroup->name, cgroup->controller[i]->name); @@ -1626,6 +1682,11 @@ int cgroup_attach_task_pid(struct cgroup *cgroup, pid_t tid) } for (i = 0; i < cgroup->index; i++) { + ret = cgroupv2_controller_enabled(cgroup->name, + cgroup->controller[i]->name); + if (ret) + return ret; + ret = cgroup_build_tasks_procs_path(path, sizeof(path), cgroup->name, cgroup->controller[i]->name); diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h index b834202dcf6b..5dcf7ee09711 100644 --- a/src/libcgroup-internal.h +++ b/src/libcgroup-internal.h @@ -350,6 +350,10 @@ int cgroup_build_tasks_procs_path(char * const path, int cgroupv2_get_subtree_control(const char *path, const char *ctrl_name, bool * const enabled); + +int cgroupv2_controller_enabled(const char * const cg_name, + const char * const ctrl_name); + #endif /* UNIT_TEST */ __END_DECLS -- 2.25.4 _______________________________________________ Libcg-devel mailing list Libcg-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libcg-devel