From 4c577f91050b1ad00e5ed2b2abb40fc4978db996 Mon Sep 17 00:00:00 2001 From: Kamalesh Babulal Date: Thu, 27 Jan 2022 12:33:52 -0700 Subject: [PATCH] api.c: add support for cgroup.threads cgroup_build_tasks_procs_path(), that builds the proc path for moving the tid, doesn't check for the cgroup type and appends cgroup.procs for both cgroup v1/v2. With cgroup v2, this results in building a wrong proc path if the cgroup type is threaded. This patch adds support to check for the cgroup v2 type and build the proc path according to the below table: cgroup.type | proc file | Description | ----------------+----------------+------------------------------------+ domain | cgroup.procs | regular cgroup, all threads gets | | | moved to the cgroup. | domain threaded | cgroup.procs | root of threaded subtree, all | | | threads gets moved to the cgroup. | threaded | cgroup.threads | cgroup under threaded subtree, | | | single threads with matching tid, | | | gets moved to the cgroup. | domain invalid | N/A | invalid state of a cgroup under the| | | threaded subtree. | Closes: https://github.com/libcgroup/libcgroup/issues/64 Signed-off-by: Kamalesh Babulal Signed-off-by: Tom Hromatka --- src/api.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/src/api.c b/src/api.c index 8f7a28c4..cf3ff6c9 100644 --- a/src/api.c +++ b/src/api.c @@ -1534,11 +1534,72 @@ char *cg_build_path(const char *name, char *path, const char *type) return path; } +static int cgroup_get_cg_type(const char * const path, char * const type, + size_t type_sz) +{ + char cg_type_path[FILENAME_MAX]; + char cg_type[LL_MAX]; + int len, err = 0; + FILE *fp = NULL; + struct stat st; + int stat_ret; + + snprintf(cg_type_path, FILENAME_MAX, "%scgroup.type", path); + /* file cgroup.type, doesn't exist for root cgroup. */ + stat_ret = stat(cg_type_path, &st); + if (stat_ret != 0) { + snprintf(type, type_sz, "cgroup.procs"); + goto out; + } + + fp = fopen(cg_type_path, "re"); + if (!fp) { + cgroup_warn("Warning: failed to open file %s: %s\n", + cg_type_path, strerror(errno)); + err = ECGOTHER; + goto out; + } + + if (fgets(cg_type, LL_MAX, fp) == NULL) { + cgroup_warn("Warning: failed to read file %s: %s\n", + cg_type_path, strerror(errno)); + err = ECGOTHER; + goto out; + } + + len = strlen(cg_type) - 1; + /* + * Append cgroup.threads to the path, if the cgroup.type is + * threaded and cgroup.procs for type domain, domain threaded. + * domain type is used for regular cgroup and domain threaded + * for root of threaded cgroup v2 subtree. Another possible + * type is domain invalid, it's an invalid state, under the + * threaded subtree. + */ + if (strncmp(cg_type, "domain", len) == 0 || + strncmp(cg_type, "domain threaded", len) == 0) { + snprintf(type, type_sz, "cgroup.procs"); + } else if (strncmp(cg_type, "threaded", len) == 0) { + snprintf(type, type_sz, "cgroup.threads"); + } else { + cgroup_warn("Warning: invalid %scgroup.type: %s\n", + path, cg_type); + err = ECGOTHER; + } + +out: + if (fp) + fclose(fp); + + return err; +} + int cgroup_build_tasks_procs_path(char * const path, size_t path_sz, const char * const cg_name, const char * const ctrl_name) { enum cg_version_t version; + char cg_type[LL_MAX]; int err = ECGOTHER; if (!cg_build_path(cg_name, path, ctrl_name)) @@ -1554,8 +1615,11 @@ int cgroup_build_tasks_procs_path(char * const path, err = 0; break; case CGROUP_V2: - strncat(path, "cgroup.procs", path_sz - strlen(path)); - err = 0; + err = cgroup_get_cg_type(path, cg_type, sizeof(cg_type)); + if (err) + goto error; + + strncat(path, cg_type , path_sz - strlen(path)); break; default: err = ECGOTHER; @@ -1566,6 +1630,8 @@ error: if (err) path[0] = '\0'; + cgroup_dbg("cgroup build procs path: %s\n", path); + return err; } -- 2.47.2