[CRIU] [PATCH] criu: Add exec-cmd option.

Deyan Doychev deyan at 1h.com
Wed Mar 19 10:39:24 PDT 2014


From: Deyan Doychev <deyandoichev at gmail.com>

The --exec-cmd option specifies a command that will be execve()-ed on successful
restore. This way the command specified here will become the parent process of
the restored process tree.

When this option is specified criu will fork to become a daemon before it starts
restoring the processes. It also implies the -d option so waiting for the
restored processes to finish is responsibility of the command specified here.

This option will be used when restoring LinuX Containers.

Signed-off-by: Deyan Doychev <deyandoichev at gmail.com>
---
 cr-restore.c         |    3 +++
 cr-service.c         |   15 +++++++++++++++
 crtools.c            |   35 ++++++++++++++++++++++++++++++++++-
 include/cr_options.h |    2 ++
 lib/criu.c           |    5 +++++
 protobuf/rpc.proto   |    1 +
 6 files changed, 60 insertions(+), 1 deletions(-)

diff --git a/cr-restore.c b/cr-restore.c
index b352daa..e528e3c 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -1600,6 +1600,9 @@ int cr_restore_tasks(void)
 {
 	int ret = -1;
 
+	if (opts.exec_cmd && daemon(1, 0))
+		return -1;
+
 	if (cr_plugin_init())
 		return -1;
 
diff --git a/cr-service.c b/cr-service.c
index 46a1004..bdb7257 100644
--- a/cr-service.c
+++ b/cr-service.c
@@ -265,6 +265,11 @@ static int setup_opts_from_req(int sk, CriuOpts *req)
 	if (req->has_force_irmap)
 		opts.force_irmap = req->force_irmap;
 
+	if (req->exec_cmd) {
+		opts.exec_cmd = parse_exec_cmd(req->exec_cmd);
+		opts.restore_detach = true;
+	}
+
 	if (req->ps) {
 		opts.use_page_server = true;
 		opts.addr = req->ps->address;
@@ -342,6 +347,7 @@ static int restore_using_req(int sk, CriuOpts *req)
 		goto exit;
 
 	success = true;
+
 exit:
 	if (send_criu_restore_resp(sk, success,
 				   root_item ? root_item->pid.real : -1) == -1) {
@@ -349,6 +355,14 @@ exit:
 		success = false;
 	}
 
+	if (success && opts.exec_cmd) {
+		close(sk);
+		extern char **environ;
+		execve(opts.exec_cmd[0], opts.exec_cmd, environ);
+		pr_perror("Failed to exec cmd %s", opts.exec_cmd[0]);
+		success = false;
+	}
+
 	return success ? 0 : 1;
 }
 
@@ -657,6 +671,7 @@ int cr_service(bool daemon_mode)
 			close(server_fd);
 			ret = cr_service_work(sk);
 			close(sk);
+
 			exit(ret != 0);
 		}
 
diff --git a/crtools.c b/crtools.c
index 047ac53..5591225 100644
--- a/crtools.c
+++ b/crtools.c
@@ -77,6 +77,23 @@ bad_ns:
 	return -1;
 }
 
+char **parse_exec_cmd(char *optarg)
+{
+	int i;
+	int count = 1;
+	char **res;
+
+	for (i = strlen(optarg); i >= 0; i--)
+		if (strchr(" \t\r\n", optarg[i]))
+			count++;
+
+	res = xmalloc(count * sizeof(char *));
+	res[0] = strtok(optarg, " \t\r\n");
+	for (i = 1; (res[i] = strtok(NULL, " \t\r\n")); i++);
+
+	return res;
+}
+
 static int parse_cpu_cap(struct cr_options *opts, const char *optarg)
 {
 	bool inverse = false;
@@ -162,6 +179,7 @@ int main(int argc, char *argv[])
 		{ "libdir", required_argument, 0, 'L'},
 		{ "cpu-cap", required_argument, 0, 57},
 		{ "force-irmap", no_argument, 0, 58},
+		{ "exec-cmd", required_argument, 0, 59},
 		{ },
 	};
 
@@ -333,6 +351,10 @@ int main(int argc, char *argv[])
 		case 'L':
 			opts.libdir = optarg;
 			break;
+		case 59:
+			opts.exec_cmd = parse_exec_cmd(optarg);
+			opts.restore_detach = true;
+			break;
 		case 'V':
 			pr_msg("Version: %s\n", CRIU_VERSION);
 			if (strcmp(CRIU_GITID, "0"))
@@ -390,7 +412,16 @@ int main(int argc, char *argv[])
 	if (!strcmp(argv[optind], "restore")) {
 		if (tree_id)
 			pr_warn("Using -t with criu restore is obsoleted\n");
-		return cr_restore_tasks() != 0;
+
+		ret = cr_restore_tasks();
+		if (ret == 0 && opts.exec_cmd) {
+			extern char **environ;
+			execve(opts.exec_cmd[0], opts.exec_cmd, environ);
+			pr_perror("Failed to exec command %s\n", opts.exec_cmd[0]);
+			ret = 1;
+		}
+
+		return ret != 0;
 	}
 
 	if (!strcmp(argv[optind], "show"))
@@ -460,6 +491,8 @@ usage:
 "                        (if not specified, value of --images-dir is used)\n"
 "     --cpu-cap CAP      require certain cpu capability. CAP: may be one of:\n"
 "                        'fpu','all'. To disable capability, prefix it with '^'.\n"
+"     --exec-cmd CMD     execute this command on successful restore making it the\n"
+"                        parent of the restored process (implies -d)\n"
 "\n"
 "* Special resources support:\n"
 "  -x|--" USK_EXT_PARAM "      allow external unix connections\n"
diff --git a/include/cr_options.h b/include/cr_options.h
index 782b866..a560324 100644
--- a/include/cr_options.h
+++ b/include/cr_options.h
@@ -48,10 +48,12 @@ struct cr_options {
 	bool			auto_dedup;
 	unsigned int		cpu_cap;
 	bool			force_irmap;
+	char			**exec_cmd;
 };
 
 extern struct cr_options opts;
 
 extern void init_opts(void);
+extern char **parse_exec_cmd(char *optarg);
 
 #endif /* __CR_OPTIONS_H__ */
diff --git a/lib/criu.c b/lib/criu.c
index 33927e8..77fdf10 100644
--- a/lib/criu.c
+++ b/lib/criu.c
@@ -110,6 +110,11 @@ void criu_set_cpu_cap(unsigned int cap)
 	opts->cpu_cap		= cap;
 }
 
+void criu_set_exec_cmd(char *cmdline)
+{
+	opts->exec_cmd = strdup(cmdline);
+}
+
 static CriuResp *recv_resp(int socket_fd)
 {
 	unsigned char buf[CR_MAX_MSG_SIZE];
diff --git a/protobuf/rpc.proto b/protobuf/rpc.proto
index 97f51fc..3e061b9 100644
--- a/protobuf/rpc.proto
+++ b/protobuf/rpc.proto
@@ -37,6 +37,7 @@ message criu_opts {
 
 	optional uint32			cpu_cap		= 20 [default = 0xffffffff];
 	optional bool			force_irmap	= 21;
+	optional string			exec_cmd	= 22;
 }
 
 message criu_dump_resp {
-- 
1.7.1



More information about the CRIU mailing list