copy = must_copy_string(entry);
else if (string_in_list(klist, entry))
copy = must_copy_string(entry);
+ else if (!strcmp(entry, "cgroup2"))
+ copy = must_copy_string(entry);
else
copy = must_prefix_named(entry);
* options. But we simply assume that the mountpoint must be
* /sys/fs/cgroup/controller-list
*/
-static char **get_controllers(char **klist, char **nlist, char *line)
+static char **get_controllers(char **klist, char **nlist, char *line, int type)
{
/* the fourth field is /sys/fs/cgroup/comma-delimited-controller-list */
int i;
char *dup, *p2, *tok;
- bool is_cgroup_v2;
char *p = line, *saveptr = NULL;
char **aret = NULL;
- /* handle cgroup v2 */
- is_cgroup_v2 = is_cgroupfs_v2(line);
-
for (i = 0; i < 4; i++) {
p = strchr(p, ' ');
if (!p)
*p2 = '\0';
/* cgroup v2 does not have separate mountpoints for controllers */
- if (is_cgroup_v2) {
+ if (type == CGROUP_V2) {
must_append_controller(klist, nlist, &aret, "cgroup2");
return aret;
}
while (getline(&line, &len, f) != -1) {
char **controller_list = NULL;
char *mountpoint, *base_cgroup;
- bool is_cgroup_v2, writeable;
+ bool writeable;
+ int type;
- is_cgroup_v2 = is_cgroupfs_v2(line);
- if (!is_cgroupfs_v1(line) && !is_cgroup_v2)
+ type = get_cgroup_version(line);
+ if (type < 0)
continue;
- controller_list = get_controllers(klist, nlist, line);
+ controller_list = get_controllers(klist, nlist, line, type);
if (!controller_list)
continue;
trim(base_cgroup);
prune_init_scope(base_cgroup);
- if (is_cgroup_v2)
+ if (type == CGROUP_V2)
writeable = test_writeable_v2(mountpoint, base_cgroup);
else
writeable = test_writeable_v1(mountpoint, base_cgroup);
#include "cgroup_utils.h"
#include "utils.h"
+int get_cgroup_version(char *line)
+{
+ if (is_cgroupfs_v1(line))
+ return CGROUP_V1;
+
+ if (is_cgroupfs_v2(line))
+ return CGROUP_V2;
+
+ return -1;
+}
+
bool is_cgroupfs_v1(char *line)
{
char *p = strstr(line, " - ");
* file.
*/
int ret;
- char *cgroup_path, *cgroup_procs_file;
+ char *cgroup_path, *cgroup_procs_file, *cgroup_threads_file;
cgroup_path = must_make_path(mountpoint, path, NULL);
cgroup_procs_file = must_make_path(cgroup_path, "cgroup.procs", NULL);
ret = access(cgroup_path, W_OK);
- free(cgroup_path);
if (ret < 0) {
+ free(cgroup_path);
free(cgroup_procs_file);
return false;
}
ret = access(cgroup_procs_file, W_OK);
free(cgroup_procs_file);
+ if (ret < 0) {
+ free(cgroup_path);
+ return false;
+ }
+
+ /* Newer versions of cgroup2 now also require write access to the
+ * "cgroup.threads" file.
+ */
+ cgroup_threads_file = must_make_path(cgroup_path, "cgroup.threads", NULL);
+ free(cgroup_path);
+ if (!file_exists(cgroup_threads_file)) {
+ free(cgroup_threads_file);
+ return true;
+ }
+
+ ret = access(cgroup_threads_file, W_OK);
+ free(cgroup_threads_file);
+ if (ret < 0)
+ return false;
return ret == 0;
}