From 7c7e53f491f5e9a67f64bca227dc9af499756f3e Mon Sep 17 00:00:00 2001 From: Liana Koleva <43767763+lianakoleva@users.noreply.github.com> Date: Fri, 6 Dec 2024 02:37:53 +0000 Subject: [PATCH] Support criu-image-streamer through RPC Programs calling CRIU through RPC may want access to image streaming for faster data transfer. To use image streaming through RPC, (1) criu-image-streamer must be started by the calling program. (2) The RPC call must enable stream in `criu_opts`. Signed-off-by: Liana Koleva <43767763+lianakoleva@users.noreply.github.com> --- criu/cr-service.c | 14 ++++------- criu/crtools.c | 52 +++++++++++++++++++-------------------- criu/include/cr_options.h | 3 ++- criu/include/crtools.h | 2 ++ images/rpc.proto | 1 + 5 files changed, 35 insertions(+), 37 deletions(-) diff --git a/criu/cr-service.c b/criu/cr-service.c index b9d11ced22..9498cd4d35 100644 --- a/criu/cr-service.c +++ b/criu/cr-service.c @@ -394,14 +394,10 @@ static int setup_opts_from_req(int sk, CriuOpts *req) if (req->parent_img) SET_CHAR_OPTS(img_parent, req->parent_img); - /* - * Image streaming is not supported with CRIU's service feature as - * the streamer must be started for each dump/restore operation. - * It is unclear how to do that with RPC, so we punt for now. - * This explains why we provide the argument mode=-1 instead of - * O_RSTR or O_DUMP. - */ - if (open_image_dir(images_dir_path, -1) < 0) { + if (req->stream) + opts.stream = true; + + if (open_image_dir(images_dir_path, image_dir_mode()) < 0) { pr_perror("Can't open images directory"); goto err; } @@ -1261,7 +1257,7 @@ static int handle_cpuinfo(int sk, CriuReq *msg) if (pid == 0) { int ret = 1; - opts.mode = CR_CPUINFO; + opts.mode = (msg->type == CRIU_REQ_TYPE__CPUINFO_DUMP) ? CR_CPUINFO_DUMP : CR_CPUINFO_CHECK; if (setup_opts_from_req(sk, msg->opts)) goto cout; diff --git a/criu/crtools.c b/criu/crtools.c index 6f493850b9..7286ced0b7 100644 --- a/criu/crtools.c +++ b/criu/crtools.c @@ -54,19 +54,17 @@ void flush_early_log_to_stderr(void) flush_early_log_buffer(STDERR_FILENO); } -static int image_dir_mode(char *argv[], int optind) +int image_dir_mode() { switch (opts.mode) { case CR_DUMP: /* fallthrough */ + case CR_CPUINFO_DUMP: + /* fallthrough */ case CR_PRE_DUMP: return O_DUMP; case CR_RESTORE: return O_RSTR; - case CR_CPUINFO: - if (!strcmp(argv[optind + 1], "dump")) - return O_DUMP; - /* fallthrough */ default: return -1; } @@ -76,7 +74,7 @@ static int image_dir_mode(char *argv[], int optind) return -1; } -static int parse_criu_mode(char *mode) +static int parse_criu_mode(char *mode, char *subcommand) { if (!strcmp(mode, "dump")) opts.mode = CR_DUMP; @@ -96,8 +94,12 @@ static int parse_criu_mode(char *mode) opts.mode = CR_SWRK; else if (!strcmp(mode, "dedup")) opts.mode = CR_DEDUP; - else if (!strcmp(mode, "cpuinfo")) - opts.mode = CR_CPUINFO; + else if (!strcmp(mode, "cpuinfo") && subcommand == NULL) + return -2; + else if (!strcmp(mode, "cpuinfo") && !strcmp(subcommand, "dump")) + opts.mode = CR_CPUINFO_DUMP; + else if (!strcmp(mode, "cpuinfo") && !strcmp(subcommand, "check")) + opts.mode = CR_CPUINFO_CHECK; else if (!strcmp(mode, "exec")) opts.mode = CR_EXEC_DEPRECATED; else if (!strcmp(mode, "show")) @@ -115,6 +117,7 @@ int main(int argc, char *argv[], char *envp[]) bool has_exec_cmd = false; bool has_sub_command; int state = PARSING_GLOBAL_CONF; + char* subcommand; BUILD_BUG_ON(CTL_32 != SYSCTL_TYPE__CTL_32); BUILD_BUG_ON(__CTL_STR != SYSCTL_TYPE__CTL_STR); @@ -165,9 +168,15 @@ int main(int argc, char *argv[], char *envp[]) return 1; } - if (parse_criu_mode(argv[optind])) { + has_sub_command = (argc - optind) > 1; + subcommand = has_sub_command ? argv[optind + 1] : NULL; + ret = parse_criu_mode(argv[optind], subcommand); + if (ret == -1) { pr_err("unknown command: %s\n", argv[optind]); goto usage; + } else if (ret == -2) { + pr_err("cpuinfo requires an action: dump or check\n"); + goto usage; } /* * util_init initializes criu_run_id and compel_run_id so that sockets @@ -200,8 +209,6 @@ int main(int argc, char *argv[], char *envp[]) if (opts.work_dir == NULL) SET_CHAR_OPTS(work_dir, opts.imgs_dir); - has_sub_command = (argc - optind) > 1; - if (has_exec_cmd) { if (!has_sub_command) { pr_err("--exec-cmd requires a command\n"); @@ -225,23 +232,20 @@ int main(int argc, char *argv[], char *envp[]) opts.exec_cmd[argc - optind - 1] = NULL; } else { /* No subcommands except for cpuinfo and restore --exec-cmd */ - if (opts.mode != CR_CPUINFO && has_sub_command) { + if (opts.mode != CR_CPUINFO_DUMP && opts.mode != CR_CPUINFO_CHECK && has_sub_command) { pr_err("excessive parameter%s for command %s\n", (argc - optind) > 2 ? "s" : "", argv[optind]); goto usage; - } else if (opts.mode == CR_CPUINFO && !has_sub_command) { - pr_err("cpuinfo requires an action: dump or check\n"); - goto usage; } } - if (opts.stream && image_dir_mode(argv, optind) == -1) { + if (opts.stream && image_dir_mode() == -1) { pr_err("--stream cannot be used with the %s command\n", argv[optind]); goto usage; } /* We must not open imgs dir, if service is called */ if (opts.mode != CR_SERVICE) { - ret = open_image_dir(opts.imgs_dir, image_dir_mode(argv, optind)); + ret = open_image_dir(opts.imgs_dir, image_dir_mode()); if (ret < 0) { pr_err("Couldn't open image dir %s\n", opts.imgs_dir); return 1; @@ -335,16 +339,10 @@ int main(int argc, char *argv[], char *envp[]) if (opts.mode == CR_DEDUP) return cr_dedup() != 0; - if (opts.mode == CR_CPUINFO) { - if (!argv[optind + 1]) { - pr_err("cpuinfo requires an action: dump or check\n"); - goto usage; - } - if (!strcmp(argv[optind + 1], "dump")) - return cpuinfo_dump(); - else if (!strcmp(argv[optind + 1], "check")) - return cpuinfo_check(); - } + if (opts.mode == CR_CPUINFO_DUMP) + return cpuinfo_dump(); + if (opts.mode == CR_CPUINFO_CHECK) + return cpuinfo_check(); if (opts.mode == CR_EXEC_DEPRECATED) { pr_err("The \"exec\" action is deprecated by the Compel library.\n"); diff --git a/criu/include/cr_options.h b/criu/include/cr_options.h index 60cf9437e6..16d0a6a92b 100644 --- a/criu/include/cr_options.h +++ b/criu/include/cr_options.h @@ -117,7 +117,8 @@ enum criu_mode { CR_SERVICE, CR_SWRK, CR_DEDUP, - CR_CPUINFO, + CR_CPUINFO_DUMP, + CR_CPUINFO_CHECK, CR_EXEC_DEPRECATED, CR_SHOW_DEPRECATED, }; diff --git a/criu/include/crtools.h b/criu/include/crtools.h index b54b9d9294..a15b1b71f6 100644 --- a/criu/include/crtools.h +++ b/criu/include/crtools.h @@ -33,6 +33,8 @@ extern int cr_lazy_pages(bool daemon); extern int check_add_feature(char *arg); extern void pr_check_features(const char *offset, const char *sep, int width); +int image_dir_mode(void); + #define PPREP_HEAD_INACTIVE ((struct pprep_head *)-1) #define add_post_prepare_cb_once(phead) \ diff --git a/images/rpc.proto b/images/rpc.proto index 1a4722a9ce..42cc535bd5 100644 --- a/images/rpc.proto +++ b/images/rpc.proto @@ -145,6 +145,7 @@ message criu_opts { optional bool leave_stopped = 69; optional bool display_stats = 70; optional bool log_to_stderr = 71; + optional bool stream = 72; /* optional bool check_mounts = 128; */ }