From: Tom Hromatka Date: Wed, 23 Sep 2020 16:41:00 +0000 (-0600) Subject: api.c: Add function to read the cgroup.subtree_control file X-Git-Tag: v2.0.rc1~21^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1a28481d680e696b872b689f2613e4a236746ff2;p=thirdparty%2Flibcgroup.git api.c: Add function to read the cgroup.subtree_control file Add a function, cgroupv2_get_subtree_control(), that verifies if a controller is enabled in the cgroup.subtree_control file for the requested path. This function will be used in the next commit - "api.c: Add function to check if a controller is enabled for a cgroup v2 cgroup" - to determine if the requested cgroup v2 controller is enabled for a cgroup. This is a required check to ensure that the cgclassify/cgexec operation will succeed. Signed-off-by: Tom Hromatka --- diff --git a/src/api.c b/src/api.c index 274718bb..88042f95 100644 --- a/src/api.c +++ b/src/api.c @@ -1884,6 +1884,72 @@ err: return error; } +/** + * Check if the requested cgroup controller is enabled on this subtree + * + * @param path Cgroup directory + * @param ctrl_name Name of the controller to check + * @param output parameter that indicates whether the controller is enabled\ + */ +STATIC int cgroupv2_get_subtree_control(const char *path, + const char *ctrl_name, + bool * const enabled) +{ + char *path_copy = NULL, *saveptr = NULL, *token, *ret_c; + int ret, error = ECGROUPNOTMOUNTED; + char buffer[FILENAME_MAX]; + FILE *fp = NULL; + + if (!path || !ctrl_name || !enabled) + return ECGOTHER; + + *enabled = false; + + path_copy = (char *)malloc(FILENAME_MAX); + if (!path_copy) + goto out; + + ret = snprintf(path_copy, FILENAME_MAX, "%s/%s", path, + CGV2_SUBTREE_CTRL_FILE); + if (ret < 0) + goto out; + + fp = fopen(path_copy, "re"); + if (!fp) { + cgroup_warn("Warning: fopen failed\n"); + last_errno = errno; + goto out; + } + + ret_c = fgets(buffer, sizeof(buffer), fp); + if (ret_c == NULL) + /* The subtree control file is empty */ + goto out; + + /* remove the trailing newline */ + ret_c[strlen(ret_c) - 1] = '\0'; + + /* Split the enabled controllers by " " and evaluate if the requested + * controller is enabled. + */ + token = strtok_r(buffer, " ", &saveptr); + do { + if (strncmp(ctrl_name, token, FILENAME_MAX) == 0) { + error = 0; + *enabled = true; + break; + } + } while ((token = strtok_r(NULL, " ", &saveptr))); + +out: + if (path_copy) + free(path_copy); + if (fp) + fclose(fp); + + return error; +} + /** * Enable/Disable a controller in the cgroup v2 subtree_control file * diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h index 72ddc19e..b834202d 100644 --- a/src/libcgroup-internal.h +++ b/src/libcgroup-internal.h @@ -347,6 +347,9 @@ int cgroup_build_tasks_procs_path(char * const path, size_t path_sz, const char * const cg_name, const char * const ctrl_name); +int cgroupv2_get_subtree_control(const char *path, + const char *ctrl_name, + bool * const enabled); #endif /* UNIT_TEST */ __END_DECLS