From: Kamalesh Babulal Date: Sun, 23 Apr 2023 11:16:48 +0000 (+0530) Subject: api.c: add cgroup v2 support to cgroup_get_current_controller_path() X-Git-Tag: v3.1.0~86 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=72ccaa389e874e70111f4a56330538441573c4e8;p=thirdparty%2Flibcgroup.git api.c: add cgroup v2 support to cgroup_get_current_controller_path() Add support to read/parse cgroup v2 format /proc//cgroup to cgroup_get_current_controller_path(). The format of /proc//cgroup remains the same: hierarchy-ID:controller-list:cgroup-path the difference is that in cgroup v2 mode: - hierarchy-ID is always 0 (one hierarchy allowed) - controller-list is empty there can also be a mix of both legacy and unified controllers for a given task if the cgroup mode is hybrid mode. This patch, add support for the mixed cgroup setup mode too. Reported-by: Adriaan Schmidt Signed-off-by: Kamalesh Babulal Signed-off-by: Tom Hromatka --- diff --git a/src/api.c b/src/api.c index 941b0755..99ca01b8 100644 --- a/src/api.c +++ b/src/api.c @@ -4805,17 +4805,37 @@ int cgroup_init_rules_cache(void) int cgroup_get_current_controller_path(pid_t pid, const char *controller, char **current_path) { FILE *pid_cgroup_fd = NULL; + enum cg_version_t version; + enum cg_setup_mode_t mode; + bool unified = false; char *path = NULL; int ret; - if (!controller) - return ECGOTHER; - if (!cgroup_initialized) { cgroup_warn("libcgroup is not initialized\n"); return ECGROUPNOTINITIALIZED; } + mode = cgroup_setup_mode(); + if (mode == CGROUP_MODE_LEGACY && !controller) + return ECGOTHER; + + /* + * both unified/hybrid can have the controller mounted as + * cgroup v2 version. + */ + if (!controller) { + unified = true; + } else { + ret = cgroup_get_controller_version(controller, &version); + if (ret) { + cgroup_warn("Failed to get version of the controller: %s\n", controller); + ret = ECGINVAL; + goto cleanup_path; + } + unified = (version == CGROUP_V2); + } + ret = asprintf(&path, "/proc/%d/cgroup", pid); if (ret <= 0) { cgroup_warn("cannot allocate memory (/proc/pid/cgroup) ret %d\n", ret); @@ -4842,6 +4862,49 @@ int cgroup_get_current_controller_path(pid_t pid, const char *controller, char * char *token; int num; + /* + * with unified mode, the /proc/pid/cgroup the output is + * similar to that of cgroup legacy and hybrid modes: + * hierarchy-ID:controller-list:cgroup-path + * + * the difference is that in cgroup v2: + * - hierarchy-ID is always 0 (one hierarchy allowed) + * - controller-list is empty + */ + if (mode == CGROUP_MODE_UNIFIED || unified) { + ret = fscanf(pid_cgroup_fd, "%d::%4096s\n", &num, cgroup_path); + if (ret != 2) { + /* + * we are interested only in unified format + * line, skip this line. + */ + if (unified) { + fscanf(pid_cgroup_fd, "%*[^\n]\n"); + continue; + } + + cgroup_warn("read failed for pid_cgroup_fd ret %d\n", ret); + last_errno = errno; + ret = ECGOTHER; + goto done; + } + + /* check if the controller is enabled in cgroup v2 */ + if (controller) { + ret = cgroupv2_controller_enabled(cgroup_path, controller); + if (ret) + goto done; + } + + *current_path = strdup(cgroup_path); + if (!*current_path) { + last_errno = errno; + ret = ECGOTHER; + } + ret = 0; + goto done; + } + /* * 4096 == FILENAME_MAX, keeping the coverity happy with precision * for the cgroup_path.