{
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,
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);
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,
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
{
struct cgroup_group_spec *ptr;
int i, j;
- char *cptr, *pathptr, *temp;
+ char *cptr = NULL, *pathptr = NULL, *temp;
ptr = *cdptr;
}
/* 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;
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);