Skip to content

Commit

Permalink
cgroupfs/cgfsng: improve cgroup2 handling
Browse files Browse the repository at this point in the history
This fixes a bunch of bugs.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
  • Loading branch information
Christian Brauner committed Nov 9, 2017
1 parent eb768a6 commit 0a5c220
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 13 deletions.
21 changes: 10 additions & 11 deletions src/lxc/cgroups/cgfsng.c
Expand Up @@ -210,6 +210,8 @@ static void must_append_controller(char **klist, char **nlist, char ***clist, ch
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);

Expand Down Expand Up @@ -740,18 +742,14 @@ static bool all_controllers_found(void)
* 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)
Expand All @@ -775,7 +773,7 @@ static char **get_controllers(char **klist, char **nlist, char *line)
*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;
}
Expand Down Expand Up @@ -1070,13 +1068,14 @@ static bool parse_hierarchies(void)
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;

Expand All @@ -1102,7 +1101,7 @@ static bool parse_hierarchies(void)

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);
Expand Down
34 changes: 32 additions & 2 deletions src/lxc/cgroups/cgroup_utils.c
Expand Up @@ -32,6 +32,17 @@
#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, " - ");
Expand Down Expand Up @@ -67,20 +78,39 @@ bool test_writeable_v2(char *mountpoint, char *path)
* 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;
}
7 changes: 7 additions & 0 deletions src/lxc/cgroups/cgroup_utils.h
Expand Up @@ -28,6 +28,13 @@
#include <stdbool.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. */
extern bool is_cgroupfs_v1(char *line);

Expand Down

0 comments on commit 0a5c220

Please sign in to comment.