From 81ccd00ec7414fc38b6d69ed711f4f68657f3284 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Mon, 4 Apr 2022 13:33:55 +0000 Subject: [PATCH] criu: add support for different manage cgroups modes This is motivated by checkpoint errors of containers restored with a new ID in Podman. Restoring a container with a new name and ID will result in a new cgroup assigned to the container. Unfortunately CRIU restores information about the original cgroup name. Now the container is running in one cgroup but partially has still old cgroup information tied to it. This adds '--manage-cgroups-mode=ignore' to crun which allows crun to tell CRIU to completely ignore anything concerning cgroups. With this change it is possible to checkpoint and restore a container multiple times with changing names and IDs. Signed-off-by: Adrian Reber --- crun.1 | 10 ++++++++++ crun.1.md | 8 ++++++++ src/checkpoint.c | 30 ++++++++++++++++++++++++++++++ src/checkpoint.h | 1 + src/libcrun/container.h | 1 + src/libcrun/criu.c | 5 +++++ src/restore.c | 7 +++++++ 7 files changed, 62 insertions(+) diff --git a/crun.1 b/crun.1 index d4f33d5da6..435a51f286 100644 --- a/crun.1 +++ b/crun.1 @@ -446,6 +446,11 @@ the pre-dump. It is important to use a relative path from the actual checkpoint directory specified via \fB--image-path\fP\&. It will fail if an absolute path is used. +.PP +\fB--manage-cgroups-mode\fP=\fIMODE\fP +Specify which CRIU mange cgroup mode should be used. Permitted values are +\fBsoft\fP, \fBignore\fP, \fBfull\fP or \fBstrict\fP\&. Default is \fBsoft\fP\&. + .SH RESTORE OPTIONS .PP crun [global options] restore [options] CONTAINER @@ -482,6 +487,11 @@ Detach from the container's process \fB--pid-file\fP=\fIFILE\fP Where to write the PID of the container +.PP +\fB--manage-cgroups-mode\fP=\fIMODE\fP +Specify which CRIU mange cgroup mode should be used. Permitted values are +\fBsoft\fP, \fBignore\fP, \fBfull\fP or \fBstrict\fP\&. Default is \fBsoft\fP\&. + .SH Extensions to OCI .SH \fB\fCrun.oci.seccomp.receiver=PATH\fR diff --git a/crun.1.md b/crun.1.md index 3f0d940d38..e48cfd92e9 100644 --- a/crun.1.md +++ b/crun.1.md @@ -351,6 +351,10 @@ the pre-dump. It is important to use a relative path from the actual checkpoint directory specified via **--image-path**. It will fail if an absolute path is used. +**--manage-cgroups-mode**=_MODE_ +Specify which CRIU manage cgroup mode should be used. Permitted values are +**soft**, **ignore**, **full** or **strict**. Default is **soft**. + ## RESTORE OPTIONS crun [global options] restore [options] CONTAINER @@ -379,6 +383,10 @@ Detach from the container's process **--pid-file**=_FILE_ Where to write the PID of the container +**--manage-cgroups-mode**=_MODE_ +Specify which CRIU manage cgroup mode should be used. Permitted values are +**soft**, **ignore**, **full** or **strict**. Default is **soft**. + # Extensions to OCI ## `run.oci.seccomp.receiver=PATH` diff --git a/src/checkpoint.c b/src/checkpoint.c index bdfc3e79d2..88b8bb37ce 100644 --- a/src/checkpoint.c +++ b/src/checkpoint.c @@ -26,6 +26,9 @@ #include #include #include +#ifdef HAVE_CRIU +# include +#endif #include "crun.h" #include "libcrun/container.h" @@ -43,6 +46,7 @@ enum OPTION_FILE_LOCKS, OPTION_PARENT_PATH, OPTION_PRE_DUMP, + OPTION_MANAGE_CGROUPS_MODE, }; static char doc[] = "OCI runtime"; @@ -61,12 +65,32 @@ static struct argp_option options[] { "parent-path", OPTION_PARENT_PATH, "DIR", 0, "path for previous criu image files in pre-dump", 0 }, { "pre-dump", OPTION_PRE_DUMP, 0, 0, "dump container's memory information only, leave the container running after this", 0 }, #endif + { "manage-cgroups-mode", OPTION_MANAGE_CGROUPS_MODE, "MODE", 0, "cgroups mode: 'soft' (default), 'ignore', 'full' and 'strict'", 0 }, { 0, } }; static char args_doc[] = "checkpoint CONTAINER"; +int +crun_parse_manage_cgroups_mode (char *param arg_unused) +{ +#ifdef HAVE_CRIU + if (strcmp (param, "soft") == 0) + return CRIU_CG_MODE_SOFT; + else if (strcmp (param, "ignore") == 0) + return CRIU_CG_MODE_IGNORE; + else if (strcmp (param, "full") == 0) + return CRIU_CG_MODE_FULL; + else if (strcmp (param, "strict") == 0) + return CRIU_CG_MODE_STRICT; + else + libcrun_fail_with_error (0, "unknown cgroup mode specified"); +#else + return 0; +#endif +} + static error_t parse_opt (int key, char *arg arg_unused, struct argp_state *state arg_unused) { @@ -111,6 +135,10 @@ parse_opt (int key, char *arg arg_unused, struct argp_state *state arg_unused) cr_options.file_locks = true; break; + case OPTION_MANAGE_CGROUPS_MODE: + cr_options.manage_cgroups_mode = crun_parse_manage_cgroups_mode (argp_mandatory_argument (arg, state)); + break; + default: return ARGP_ERR_UNKNOWN; } @@ -131,6 +159,8 @@ crun_command_checkpoint (struct crun_global_arguments *global_args, int argc, ch 0, }; + cr_options.manage_cgroups_mode = -1; + argp_parse (&run_argp, argc, argv, ARGP_IN_ORDER, &first_arg, &cr_options); crun_assert_n_args (argc - first_arg, 1, 2); diff --git a/src/checkpoint.h b/src/checkpoint.h index 837f80ff0e..21230a2c42 100644 --- a/src/checkpoint.h +++ b/src/checkpoint.h @@ -20,6 +20,7 @@ #include "crun.h" +int crun_parse_manage_cgroups_mode (char *param); int crun_command_checkpoint (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *error); #endif diff --git a/src/libcrun/container.h b/src/libcrun/container.h index d7ab973d65..e599b348b6 100644 --- a/src/libcrun/container.h +++ b/src/libcrun/container.h @@ -98,6 +98,7 @@ struct libcrun_checkpoint_restore_s const char *console_socket; char *parent_path; bool pre_dump; + int manage_cgroups_mode; }; typedef struct libcrun_checkpoint_restore_s libcrun_checkpoint_restore_t; diff --git a/src/libcrun/criu.c b/src/libcrun/criu.c index df9a756daf..83989ad6bb 100644 --- a/src/libcrun/criu.c +++ b/src/libcrun/criu.c @@ -488,6 +488,11 @@ libcrun_container_checkpoint_linux_criu (libcrun_container_status_t *status, lib criu_set_tcp_established (cr_options->tcp_established); criu_set_file_locks (cr_options->file_locks); criu_set_orphan_pts_master (true); + if (cr_options->manage_cgroups_mode == -1) + /* Defaulting to CRIU_CG_MODE_SOFT just as runc */ + criu_set_manage_cgroups_mode (CRIU_CG_MODE_SOFT); + else + criu_set_manage_cgroups_mode (cr_options->manage_cgroups_mode); criu_set_manage_cgroups (true); ret = criu_dump (); diff --git a/src/restore.c b/src/restore.c index 1c72d072c7..1c7498bbdf 100644 --- a/src/restore.c +++ b/src/restore.c @@ -28,6 +28,7 @@ #include #include "crun.h" +#include "checkpoint.h" #include "libcrun/container.h" #include "libcrun/status.h" #include "libcrun/utils.h" @@ -42,6 +43,7 @@ enum OPTION_PID_FILE, OPTION_CONSOLE_SOCKET, OPTION_FILE_LOCKS, + OPTION_MANAGE_CGROUPS_MODE, }; static char doc[] = "OCI runtime"; @@ -64,6 +66,7 @@ static struct argp_option options[] { "console-socket", OPTION_CONSOLE_SOCKET, "SOCKET", 0, "path to a socket that will receive the master end of the tty", 0 }, { "file-locks", OPTION_FILE_LOCKS, 0, 0, "allow file locks", 0 }, + { "manage-cgroups-mode", OPTION_MANAGE_CGROUPS_MODE, "MODE", 0, "cgroups mode: 'soft' (default), 'ignore', 'full' and 'strict'", 0 }, { 0, } }; @@ -118,6 +121,10 @@ parse_opt (int key, char *arg arg_unused, struct argp_state *state arg_unused) crun_context.pid_file = argp_mandatory_argument (arg, state); break; + case OPTION_MANAGE_CGROUPS_MODE: + cr_options.manage_cgroups_mode = crun_parse_manage_cgroups_mode (argp_mandatory_argument (arg, state)); + break; + default: return ARGP_ERR_UNKNOWN; }