Skip to content

Commit

Permalink
cgroup: make target cgroup threaded if needed
Browse files Browse the repository at this point in the history
if moving a process fails with EOPNOTSUPP, then change the target
cgroup type to threaded and attempt the migration again.

Closes: containers#923

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
  • Loading branch information
giuseppe committed May 26, 2022
1 parent c9e60c0 commit 1ce198f
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 11 deletions.
14 changes: 13 additions & 1 deletion src/libcrun/cgroup-setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,19 @@ enter_cgroup_v2 (pid_t pid, pid_t init_pid, const char *path, bool create_if_mis
if (LIKELY (ret >= 0))
return ret;

/* If the cgroup is not being created, try to handle EBUSY. */
if (UNLIKELY (crun_error_get_errno (err) == EOPNOTSUPP))
{
crun_error_release (err);

ret = make_cgroup_threaded (path, err);
if (UNLIKELY (ret < 0))
return ret;

ret = write_file (cgroup_path_procs, pid_str, strlen (pid_str), err);
if (LIKELY (ret >= 0))
return ret;
}

if (create_if_missing || crun_error_get_errno (err) != EBUSY)
return ret;

Expand Down
98 changes: 88 additions & 10 deletions src/libcrun/cgroup-utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,41 @@ libcrun_cgroups_create_symlinks (int dirfd, libcrun_error_t *err)
return 0;
}

int
make_cgroup_threaded (const char *path, libcrun_error_t *err)
{
cleanup_free char *cgroup_path_type = NULL;
int ret;

path = consume_slashes (path);

if (path == NULL || path[0] == '\0')
return 0;

ret = append_paths (&cgroup_path_type, err, CGROUP_ROOT, path, "cgroup.type", NULL);
if (UNLIKELY (ret < 0))
return ret;

ret = write_file (cgroup_path_type, "threaded", strlen ("threaded"), err);
if (UNLIKELY (ret < 0 && errno == EOPNOTSUPP))
{
cleanup_free char *buffer = xstrdup (path);
const char *parent = consume_slashes (dirname (buffer));
if (parent[0])
{

crun_error_release (err);

ret = make_cgroup_threaded (parent, err);
if (ret < 0)
return ret;

return write_file (cgroup_path_type, "threaded", strlen ("threaded"), err);
}
}
return ret;
}

int
move_process_to_cgroup (pid_t pid, const char *subsystem, const char *path, libcrun_error_t *err)
{
Expand All @@ -85,7 +120,33 @@ move_process_to_cgroup (pid_t pid, const char *subsystem, const char *path, libc

sprintf (pid_str, "%d", pid);

return write_file (cgroup_path_procs, pid_str, strlen (pid_str), err);
ret = write_file (cgroup_path_procs, pid_str, strlen (pid_str), err);
if (UNLIKELY (ret < 0))
{
if (crun_error_get_errno (err) == EOPNOTSUPP)
{
libcrun_error_t tmp_err = NULL;
int mode;

mode = libcrun_get_cgroup_mode (err);
if (UNLIKELY (mode < 0 || mode != CGROUP_MODE_UNIFIED))
{
crun_error_release (&tmp_err);
return ret;
}

crun_error_release (err);

ret = make_cgroup_threaded (path, err);
if (UNLIKELY (ret < 0))
return ret;

return write_file (cgroup_path_procs, pid_str, strlen (pid_str), err);
}

return ret;
}
return ret;
}

int
Expand Down Expand Up @@ -648,7 +709,9 @@ read_available_controllers (const char *path, libcrun_error_t *err)
char buf[256];
ssize_t ret;

xasprintf (&controllers, "%s/cgroup.controllers", path);
ret = append_paths (&controllers, err, CGROUP_ROOT, path, "cgroup.controllers", NULL);
if (UNLIKELY (ret < 0))
return ret;

fd = TEMP_FAILURE_RETRY (open (controllers, O_RDONLY | O_CLOEXEC));
if (UNLIKELY (fd < 0))
Expand Down Expand Up @@ -691,7 +754,9 @@ write_controller_file (const char *path, int controllers_to_enable, libcrun_erro
(controllers_to_enable & CGROUP_PIDS) ? "+pids" : "", (controllers_to_enable & CGROUP_CPUSET) ? "+cpuset" : "",
(controllers_to_enable & CGROUP_HUGETLB) ? "+hugetlb" : "");

xasprintf (&subtree_control, "%s/cgroup.subtree_control", path);
ret = append_paths (&subtree_control, err, CGROUP_ROOT, path, "cgroup.subtree_control", NULL);
if (UNLIKELY (ret < 0))
return ret;
ret = write_file (subtree_control, controllers, controllers_len, err);
if (UNLIKELY (ret < 0))
{
Expand All @@ -702,7 +767,7 @@ write_controller_file (const char *path, int controllers_to_enable, libcrun_erro
int e;

e = crun_error_get_errno (err);
if (e != EPERM && e != EACCES && e != EBUSY && e != ENOENT)
if (e != EPERM && e != EACCES && e != EBUSY && e != ENOENT && e != EOPNOTSUPP)
return ret;

/* ENOENT can mean both that the file doesn't exist or the controller is not present. */
Expand Down Expand Up @@ -742,10 +807,23 @@ write_controller_file (const char *path, int controllers_to_enable, libcrun_erro
ret = write_file (subtree_control, token, strlen (token), err);
if (ret < 0)
{
if (crun_error_get_errno (err) == EBUSY)
repeat = true;
e = crun_error_get_errno (err);
crun_error_release (err);

if (e == EOPNOTSUPP)
{
make_cgroup_threaded (path, err);

ret = make_cgroup_threaded (path, err);
if (UNLIKELY (ret < 0))
return ret;

repeat = true;
}

if (e == EBUSY)
repeat = true;

continue;
}

Expand Down Expand Up @@ -789,22 +867,22 @@ enable_controllers (const char *path, libcrun_error_t *err)

xasprintf (&tmp_path, "%s/", path);

ret = read_available_controllers (CGROUP_ROOT, err);
ret = read_available_controllers ("", err);
if (UNLIKELY (ret < 0))
return ret;

controllers_to_enable = ret;

/* Enable all possible controllers in the root cgroup. */
ret = write_controller_file (CGROUP_ROOT, controllers_to_enable, err);
ret = write_controller_file ("", controllers_to_enable, err);
if (UNLIKELY (ret < 0))
{
/* Enabling +cpu when there are realtime processes fail with EINVAL. */
if ((controllers_to_enable & CGROUP_CPU) && (crun_error_get_errno (err) == EINVAL))
{
crun_error_release (err);
controllers_to_enable &= ~CGROUP_CPU;
ret = write_controller_file (CGROUP_ROOT, controllers_to_enable, err);
ret = write_controller_file ("", controllers_to_enable, err);
}
if (UNLIKELY (ret < 0))
return ret;
Expand All @@ -827,7 +905,7 @@ enable_controllers (const char *path, libcrun_error_t *err)

if (next_slash)
{
ret = write_controller_file (cgroup_path, controllers_to_enable, err);
ret = write_controller_file (tmp_path, controllers_to_enable, err);
if (UNLIKELY (ret < 0))
return ret;
}
Expand Down
2 changes: 2 additions & 0 deletions src/libcrun/cgroup-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,6 @@ int libcrun_get_cgroup_mode (libcrun_error_t *err);

int libcrun_get_cgroup_dirfd (struct libcrun_cgroup_status *status, const char *sub_cgroup, libcrun_error_t *err);

int make_cgroup_threaded (const char *path, libcrun_error_t *err);

#endif

0 comments on commit 1ce198f

Please sign in to comment.