Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cgroup: make target cgroup threaded if needed #931

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
100 changes: 88 additions & 12 deletions src/libcrun/cgroup-utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,21 +71,83 @@ 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;
const char *const threaded = "threaded";
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)
{
cleanup_free char *cgroup_path_procs = NULL;
char pid_str[16];
int ret;

ret = append_paths (&cgroup_path_procs, err, CGROUP_ROOT, subsystem ? subsystem : "", path ? path : "",
ret = append_paths (&cgroup_path_procs, err, CGROUP_ROOT,
subsystem ? subsystem : "", path ? path : "",
"cgroup.procs", NULL);
if (UNLIKELY (ret < 0))
return ret;

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)
giuseppe marked this conversation as resolved.
Show resolved Hide resolved
{
libcrun_error_t tmp_err = NULL;
int mode;

mode = libcrun_get_cgroup_mode (&tmp_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 @@ -174,7 +236,7 @@ read_pids_cgroup (int dfd, bool recurse, pid_t **pids, size_t *n_pids, size_t *a

tasksfd = openat (dfd, "cgroup.procs", O_RDONLY | O_CLOEXEC);
if (tasksfd < 0)
return crun_make_error (err, errno, "open cgroup.procs");
return crun_make_error (err, errno, "open `cgroup.procs`");

ret = read_all_fd (tasksfd, "cgroup.procs", &buffer, &len, err);
if (UNLIKELY (ret < 0))
Expand Down Expand Up @@ -648,7 +710,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 +755,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 +768,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 +808,20 @@ 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 == EBUSY)
repeat = true;
else if (e == EOPNOTSUPP)
{
ret = make_cgroup_threaded (path, err);
if (UNLIKELY (ret < 0))
return ret;

repeat = true;
}

continue;
}

Expand Down Expand Up @@ -789,22 +865,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 +903,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
2 changes: 1 addition & 1 deletion tests/podman/run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,6 @@ export TMPDIR=/var/tmp
# Does not work inside test environment.


ginkgo --focus='.*' --skip='.*(selinux|notify_socket|systemd|podman run exit 12*|podman run exit code on failure to exec|failed to start|search|trust|inspect|logs|generate|import|mounted rw|inherit host devices|play kube|cgroups=disabled|privileged CapEff|device-cgroup-rule|capabilities|network|pull from docker|--add-host|removes a pod with a container|prune removes a pod with a stopped container|overlay volume flag|prune unused images|podman images filter|image list filter|create --pull|podman ps json format|using journald for container|image tree|--pull|shared layers|child images|cached images|flag with multiple mounts|overlay and used as workdir|image_copy_tmp_dir|Podman run with specified static IPv6 has correct IP|authenticated push).*' \
ginkgo --focus='.*' --skip='.*(selinux|notify_socket|systemd|podman run exit 12*|podman run exit code on failure to exec|failed to start|search|trust|inspect|logs|generate|import|mounted rw|inherit host devices|play kube|cgroups=disabled|privileged CapEff|device-cgroup-rule|capabilities|network|pull from docker|--add-host|removes a pod with a container|prune removes a pod with a stopped container|overlay volume flag|prune unused images|podman images filter|image list filter|create --pull|podman ps json format|using journald for container|image tree|--pull|shared layers|child images|cached images|flag with multiple mounts|overlay and used as workdir|image_copy_tmp_dir|Podman run with specified static IPv6 has correct IP|authenticated push|podman kill paused container).*' \
-v -tags "seccomp ostree selinux varlink exclude_graphdriver_devicemapper" \
-timeout=50m -cover -flakeAttempts 3 -progress -trace -noColor test/e2e/.