]> git.ipfire.org Git - thirdparty/libcgroup.git/commitdiff
cgcreate, tools: Allow cgroup creation with no controllers attached
authorTom Hromatka <tom.hromatka@oracle.com>
Wed, 9 Feb 2022 19:28:44 +0000 (12:28 -0700)
committerTom Hromatka <tom.hromatka@oracle.com>
Thu, 10 Feb 2022 21:13:51 +0000 (14:13 -0700)
Add support for creating a cgroup with no controllers attached.  This
is only supported on cgroup v2.

Signed-off-by: Tom Hromatka <tom.hromatka@oracle.com>
Reviewed-by: Kamalesh Babulal <kamalesh.babulal@oracle.com>
src/abstraction-common.c
src/api.c
src/tools/tools-common.c

index 35c0aba81176859081f7911b4395e8707c8947f7..f8630ddbef0c16066373684b53b91dd63ec5a262 100644 (file)
@@ -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) {
index c13e27c790d5032dafe2030cfaabf8289288f5a3..8f3a404218332ea8e95119a4c8b11d24370f1fa5 100644 (file)
--- 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
index 4b0efa8b216b4d7acf8871c605a4cfb7a92d0c0c..c123eda2bda3f143de4921f35b421f3241a83d0e 100644 (file)
@@ -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 && j<CG_CONTROLLER_MAX-1);
+                       j++;
+               } while (temp && j<CG_CONTROLLER_MAX-1);
+       }
 
        /* Store path to the cgroup */
        strncpy(cdptr[i]->path, pathptr, FILENAME_MAX - 1);