cgroupfs/cgfsng: improve cgroup2 handling

This fixes a bunch of bugs. Signed-off-by: 's avatarChristian Brauner <christian.brauner@ubuntu.com>
parent e2deb1d8
...@@ -215,6 +215,8 @@ static void must_append_controller(char **klist, char **nlist, char ***clist, ch ...@@ -215,6 +215,8 @@ static void must_append_controller(char **klist, char **nlist, char ***clist, ch
copy = must_copy_string(entry); copy = must_copy_string(entry);
else if (string_in_list(klist, entry)) else if (string_in_list(klist, entry))
copy = must_copy_string(entry); copy = must_copy_string(entry);
else if (!strcmp(entry, "cgroup2"))
copy = must_copy_string(entry);
else else
copy = must_prefix_named(entry); copy = must_prefix_named(entry);
...@@ -749,18 +751,14 @@ static bool all_controllers_found(void) ...@@ -749,18 +751,14 @@ static bool all_controllers_found(void)
* options. But we simply assume that the mountpoint must be * options. But we simply assume that the mountpoint must be
* /sys/fs/cgroup/controller-list * /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 */ /* the fourth field is /sys/fs/cgroup/comma-delimited-controller-list */
int i; int i;
char *dup, *p2, *tok; char *dup, *p2, *tok;
bool is_cgroup_v2;
char *p = line, *saveptr = NULL; char *p = line, *saveptr = NULL;
char **aret = NULL; char **aret = NULL;
/* handle cgroup v2 */
is_cgroup_v2 = is_cgroupfs_v2(line);
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
p = strchr(p, ' '); p = strchr(p, ' ');
if (!p) if (!p)
...@@ -784,7 +782,7 @@ static char **get_controllers(char **klist, char **nlist, char *line) ...@@ -784,7 +782,7 @@ static char **get_controllers(char **klist, char **nlist, char *line)
*p2 = '\0'; *p2 = '\0';
/* cgroup v2 does not have separate mountpoints for controllers */ /* cgroup v2 does not have separate mountpoints for controllers */
if (is_cgroup_v2) { if (type == CGROUP_V2) {
must_append_controller(klist, nlist, &aret, "cgroup2"); must_append_controller(klist, nlist, &aret, "cgroup2");
return aret; return aret;
} }
...@@ -1083,13 +1081,14 @@ static bool parse_hierarchies(void) ...@@ -1083,13 +1081,14 @@ static bool parse_hierarchies(void)
while (getline(&line, &len, f) != -1) { while (getline(&line, &len, f) != -1) {
char **controller_list = NULL; char **controller_list = NULL;
char *mountpoint, *base_cgroup; char *mountpoint, *base_cgroup;
bool is_cgroup_v2, writeable; bool writeable;
int type;
is_cgroup_v2 = is_cgroupfs_v2(line); type = get_cgroup_version(line);
if (!is_cgroupfs_v1(line) && !is_cgroup_v2) if (type < 0)
continue; continue;
controller_list = get_controllers(klist, nlist, line); controller_list = get_controllers(klist, nlist, line, type);
if (!controller_list) if (!controller_list)
continue; continue;
...@@ -1115,7 +1114,7 @@ static bool parse_hierarchies(void) ...@@ -1115,7 +1114,7 @@ static bool parse_hierarchies(void)
trim(base_cgroup); trim(base_cgroup);
prune_init_scope(base_cgroup); prune_init_scope(base_cgroup);
if (is_cgroup_v2) if (type == CGROUP_V2)
writeable = test_writeable_v2(mountpoint, base_cgroup); writeable = test_writeable_v2(mountpoint, base_cgroup);
else else
writeable = test_writeable_v1(mountpoint, base_cgroup); writeable = test_writeable_v1(mountpoint, base_cgroup);
......
...@@ -32,6 +32,17 @@ ...@@ -32,6 +32,17 @@
#include "cgroup_utils.h" #include "cgroup_utils.h"
#include "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) bool is_cgroupfs_v1(char *line)
{ {
char *p = strstr(line, " - "); char *p = strstr(line, " - ");
...@@ -67,20 +78,39 @@ bool test_writeable_v2(char *mountpoint, char *path) ...@@ -67,20 +78,39 @@ bool test_writeable_v2(char *mountpoint, char *path)
* file. * file.
*/ */
int ret; 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_path = must_make_path(mountpoint, path, NULL);
cgroup_procs_file = must_make_path(cgroup_path, "cgroup.procs", NULL); cgroup_procs_file = must_make_path(cgroup_path, "cgroup.procs", NULL);
ret = access(cgroup_path, W_OK); ret = access(cgroup_path, W_OK);
free(cgroup_path);
if (ret < 0) { if (ret < 0) {
free(cgroup_path);
free(cgroup_procs_file); free(cgroup_procs_file);
return false; return false;
} }
ret = access(cgroup_procs_file, W_OK); ret = access(cgroup_procs_file, W_OK);
free(cgroup_procs_file); 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; return ret == 0;
} }
...@@ -28,6 +28,13 @@ ...@@ -28,6 +28,13 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#define CGROUP_V1 0
#define CGROUP_V2 1
#define LXCFS_CGROUP 2
/* Retrieve the cgroup version of a given entry from /proc/<pid>/mountinfo. */
extern int get_cgroup_version(char *line);
/* Check if given entry from /proc/<pid>/mountinfo is a cgroupfs v1 mount. */ /* Check if given entry from /proc/<pid>/mountinfo is a cgroupfs v1 mount. */
extern bool is_cgroupfs_v1(char *line); extern bool is_cgroupfs_v1(char *line);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment