From: Tom Hromatka Date: Wed, 9 Feb 2022 19:28:44 +0000 (-0700) Subject: cgcreate, tools: Allow cgroup creation with no controllers attached X-Git-Tag: v3.0~206^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=498530a1d7447e689ed555170b6f8e20471317bc;p=thirdparty%2Flibcgroup.git cgcreate, tools: Allow cgroup creation with no controllers attached Add support for creating a cgroup with no controllers attached. This is only supported on cgroup v2. Signed-off-by: Tom Hromatka Reviewed-by: Kamalesh Babulal --- diff --git a/src/abstraction-common.c b/src/abstraction-common.c index 35c0aba8..f8630ddb 100644 --- a/src/abstraction-common.c +++ b/src/abstraction-common.c @@ -270,7 +270,14 @@ int cgroup_convert_cgroup(struct cgroup * const out_cgroup, in_cgroup->controller[i]->version = in_version; } - cgc->version = out_version; + if (strcmp(CGROUP_FILE_PREFIX, cgc->name) == 0) + /* + * libcgroup only supports accessing cgroup.* files on + * cgroup v2 filesystems. + */ + cgc->version = CGROUP_V2; + else + cgc->version = out_version; if (cgc->version == CGROUP_UNK || cgc->version == CGROUP_DISK) { diff --git a/src/api.c b/src/api.c index c13e27c7..8f3a4042 100644 --- a/src/api.c +++ b/src/api.c @@ -1485,15 +1485,19 @@ char *cg_build_path_locked(const char *name, char *path, { int i, ret; for (i = 0; cg_mount_table[i].name[0] != '\0'; i++) { - /* Two ways to successfully move forward here: + /* Three ways to successfully move forward here: * 1. The "type" controller matches the name of a mounted * controller * 2. The "type" controller requested is "cgroup" and there's * a "real" controller mounted as cgroup v2 + * 3. The "type" controller is NULL and there's a "real" + * controller mounted as cgroup v2. This allows a user + * to create a v2 cgroup with no controllers enabled */ - if ((strcmp(cg_mount_table[i].name, type) == 0) || - (strcmp(type, CGROUP_FILE_PREFIX) == 0 && - cg_mount_table[i].version == CGROUP_V2)) { + if ((type && strcmp(cg_mount_table[i].name, type) == 0) || + (type && strcmp(type, CGROUP_FILE_PREFIX) == 0 && + cg_mount_table[i].version == CGROUP_V2) || + (type == NULL && cg_mount_table[i].version == CGROUP_V2)) { if (cg_namespace_table[i]) { ret = snprintf(path, FILENAME_MAX, "%s/%s/", cg_mount_table[i].mount.path, @@ -2435,29 +2439,39 @@ static int _cgroup_create_cgroup(const struct cgroup * const cgroup, fts_path[1] = NULL; path = fts_path[0]; - if (!cg_build_path(cgroup->name, path, controller->name)) - goto err; - - error = cgroup_get_controller_version(controller->name, &version); - if (error) - goto err; - - if (version == CGROUP_V2) { - char *parent, *dname; - - parent = strdup(path); - if (!parent) { + if (controller) { + if (!cg_build_path(cgroup->name, path, controller->name)) { error = ECGOTHER; goto err; } - dname = dirname(parent); - - error = cgroupv2_subtree_control_recursive(dname, - controller->name, true); - free(parent); + error = cgroup_get_controller_version(controller->name, + &version); if (error) goto err; + + if (version == CGROUP_V2) { + char *parent, *dname; + + parent = strdup(path); + if (!parent) { + error = ECGOTHER; + goto err; + } + + dname = dirname(parent); + + error = cgroupv2_subtree_control_recursive(dname, + controller->name, true); + free(parent); + if (error) + goto err; + } + } else { + if (!cg_build_path(cgroup->name, path, NULL)) { + error = ECGOTHER; + goto err; + } } error = cg_create_control_group(path); @@ -2488,9 +2502,11 @@ static int _cgroup_create_cgroup(const struct cgroup * const cgroup, if (error) goto err; - error = cgroup_set_values_recursive(base, controller, false); - if (error) - goto err; + if (controller) { + error = cgroup_set_values_recursive(base, controller, false); + if (error) + goto err; + } if (!ignore_ownership && version == CGROUP_V1) { error = cgroup_chown_chmod_tasks(base, @@ -2532,6 +2548,14 @@ int cgroup_create_cgroup(struct cgroup *cgroup, int ignore_ownership) return ECGROUPSUBSYSNOTMOUNTED; } + + if (cgroup->index == 0) { + /* create an empty cgroup v2 cgroup */ + error = _cgroup_create_cgroup(cgroup, NULL, ignore_ownership); + if (error) + return error; + } + /* * XX: One important test to be done is to check, if you have multiple * subsystems mounted at one point, all of them *have* be on the cgroup diff --git a/src/tools/tools-common.c b/src/tools/tools-common.c index 4b0efa8b..c123eda2 100644 --- a/src/tools/tools-common.c +++ b/src/tools/tools-common.c @@ -34,7 +34,7 @@ int parse_cgroup_spec(struct cgroup_group_spec **cdptr, char *optarg, { struct cgroup_group_spec *ptr; int i, j; - char *cptr, *pathptr, *temp; + char *cptr = NULL, *pathptr = NULL, *temp; ptr = *cdptr; @@ -52,13 +52,20 @@ int parse_cgroup_spec(struct cgroup_group_spec **cdptr, char *optarg, } /* Extract list of controllers */ - cptr = strtok(optarg, ":"); - cgroup_dbg("list of controllers is %s\n", cptr); - if (!cptr) - return -1; + if (optarg[0] == ':') { + /* No controller was passed in */ + cptr = NULL; + pathptr = strtok(optarg, ":"); + } else { + /* Extract the list of controllers from the user */ + cptr = strtok(optarg, ":"); + cgroup_dbg("list of controllers is %s\n", cptr); + if (!cptr) + return -1; + + pathptr = strtok(NULL, ":"); + } - /* Extract cgroup path */ - pathptr = strtok(NULL, ":"); cgroup_dbg("cgroup path is %s\n", pathptr); if (!pathptr) return -1; @@ -69,24 +76,27 @@ int parse_cgroup_spec(struct cgroup_group_spec **cdptr, char *optarg, fprintf(stderr, "%s\n", strerror(errno)); return -1; } - /* Convert list of controllers into an array of strings. */ - j = 0; - do { - if (j == 0) - temp = strtok(cptr, ","); - else - temp = strtok(NULL, ","); - - if (temp) { - cdptr[i]->controllers[j] = strdup(temp); - if (!cdptr[i]->controllers[j]) { - free(cdptr[i]); - fprintf(stderr, "%s\n", strerror(errno)); - return -1; + + if (cptr != NULL) { + /* Convert list of controllers into an array of strings. */ + j = 0; + do { + if (j == 0) + temp = strtok(cptr, ","); + else + temp = strtok(NULL, ","); + + if (temp) { + cdptr[i]->controllers[j] = strdup(temp); + if (!cdptr[i]->controllers[j]) { + free(cdptr[i]); + fprintf(stderr, "%s\n", strerror(errno)); + return -1; + } } - } - j++; - } while (temp && jpath, pathptr, FILENAME_MAX - 1);