Blob Blame History Raw
From 7b5909592881607f5d5ecc8de144e5bb83f02438 Mon Sep 17 00:00:00 2001
From: Adrian Reber <areber@redhat.com>
Date: Fri, 3 Dec 2021 14:32:33 +0000
Subject: [PATCH 080/120] libcriu: add single pre-dump support

In contrast to the CLI it is not possible to do a single pre-dump via
RPC and thus libcriu. In cr-service.c pre-dump always goes into a
pre-dump loop followed by a final dump. runc already works around this
to only do a single pre-dump by killing the CRIU process waiting for the
message for the final dump.

Trying to implement pre-dump in crun via libcriu it is not as easy to
work around CRIU's pre-dump loop expectations as with runc that directly
talks to CRIU via RPC.

We know that LXC/LXD also does single pre-dumps using the CLI and runc
also only does single pre-dumps by misusing the pre-dump loop interface.

With this commit it is possible to trigger a single pre-dump via RPC and
libcriu without misusing the interface provided via cr-service.c. So
this commit basically updates CRIU to the existing use cases.

The existing pre-dump loop still sounds like a very good idea, but so
far most tools have decided to implement the pre-dump loop themselves.

With this change we can implement pre-dump in crun to match what is
currently implemented in runc.

Signed-off-by: Adrian Reber <areber@redhat.com>
---
 criu/cr-service.c | 13 ++++++++-----
 images/rpc.proto  |  2 ++
 lib/c/criu.c      | 21 ++++++++++++++++++---
 lib/c/criu.h      |  2 ++
 4 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/criu/cr-service.c b/criu/cr-service.c
index 0f8bc4cc1..80d12c7b0 100644
--- a/criu/cr-service.c
+++ b/criu/cr-service.c
@@ -169,11 +169,11 @@ int send_criu_dump_resp(int socket_fd, bool success, bool restored)
 	return send_criu_msg(socket_fd, &msg);
 }
 
-static int send_criu_pre_dump_resp(int socket_fd, bool success)
+static int send_criu_pre_dump_resp(int socket_fd, bool success, bool single)
 {
 	CriuResp msg = CRIU_RESP__INIT;
 
-	msg.type = CRIU_REQ_TYPE__PRE_DUMP;
+	msg.type = single ? CRIU_REQ_TYPE__SINGLE_PRE_DUMP : CRIU_REQ_TYPE__PRE_DUMP;
 	msg.success = success;
 	set_resp_err(&msg);
 
@@ -845,7 +845,7 @@ out:
 	return send_criu_msg(sk, &resp);
 }
 
-static int pre_dump_using_req(int sk, CriuOpts *req)
+static int pre_dump_using_req(int sk, CriuOpts *req, bool single)
 {
 	int pid, status;
 	bool success = false;
@@ -886,7 +886,7 @@ static int pre_dump_using_req(int sk, CriuOpts *req)
 
 	success = true;
 out:
-	if (send_criu_pre_dump_resp(sk, success) == -1) {
+	if (send_criu_pre_dump_resp(sk, success, single) == -1) {
 		pr_perror("Can't send pre-dump resp");
 		success = false;
 	}
@@ -899,7 +899,7 @@ static int pre_dump_loop(int sk, CriuReq *msg)
 	int ret;
 
 	do {
-		ret = pre_dump_using_req(sk, msg->opts);
+		ret = pre_dump_using_req(sk, msg->opts, false);
 		if (ret < 0)
 			return ret;
 
@@ -1271,6 +1271,9 @@ more:
 	case CRIU_REQ_TYPE__VERSION:
 		ret = handle_version(sk, msg);
 		break;
+	case CRIU_REQ_TYPE__SINGLE_PRE_DUMP:
+		ret = pre_dump_using_req(sk, msg->opts, true);
+		break;
 
 	default:
 		send_criu_err(sk, "Invalid req");
diff --git a/images/rpc.proto b/images/rpc.proto
index a9f51ac4b..1d3befd23 100644
--- a/images/rpc.proto
+++ b/images/rpc.proto
@@ -172,6 +172,8 @@ enum criu_req_type {
 
 	WAIT_PID	= 11;
 	PAGE_SERVER_CHLD = 12;
+
+	SINGLE_PRE_DUMP = 13;
 }
 
 /*
diff --git a/lib/c/criu.c b/lib/c/criu.c
index 4ee189aca..500574e33 100644
--- a/lib/c/criu.c
+++ b/lib/c/criu.c
@@ -1527,7 +1527,7 @@ int criu_check(void)
 	return criu_local_check(global_opts);
 }
 
-int criu_local_dump(criu_opts *opts)
+static int dump(bool pre_dump, criu_opts *opts)
 {
 	int ret = -1;
 	CriuReq req = CRIU_REQ__INIT;
@@ -1535,7 +1535,7 @@ int criu_local_dump(criu_opts *opts)
 
 	saved_errno = 0;
 
-	req.type = CRIU_REQ_TYPE__DUMP;
+	req.type = pre_dump ? CRIU_REQ_TYPE__SINGLE_PRE_DUMP : CRIU_REQ_TYPE__DUMP;
 	req.opts = opts->rpc;
 
 	ret = send_req_and_recv_resp(opts, &req, &resp);
@@ -1543,7 +1543,7 @@ int criu_local_dump(criu_opts *opts)
 		goto exit;
 
 	if (resp->success) {
-		if (resp->dump->has_restored && resp->dump->restored)
+		if (!pre_dump && resp->dump->has_restored && resp->dump->restored)
 			ret = 1;
 		else
 			ret = 0;
@@ -1561,11 +1561,26 @@ exit:
 	return ret;
 }
 
+int criu_local_dump(criu_opts *opts)
+{
+	return dump(false, opts);
+}
+
 int criu_dump(void)
 {
 	return criu_local_dump(global_opts);
 }
 
+int criu_local_pre_dump(criu_opts *opts)
+{
+	return dump(true, opts);
+}
+
+int criu_pre_dump(void)
+{
+	return criu_local_pre_dump(global_opts);
+}
+
 int criu_local_dump_iters(criu_opts *opts, int (*more)(criu_predump_info pi))
 {
 	int ret = -1, fd = -1, uret;
diff --git a/lib/c/criu.h b/lib/c/criu.h
index a374b37f8..c6d4f50a8 100644
--- a/lib/c/criu.h
+++ b/lib/c/criu.h
@@ -161,6 +161,7 @@ int criu_get_orphan_pts_master_fd(void);
  */
 int criu_check(void);
 int criu_dump(void);
+int criu_pre_dump(void);
 int criu_restore(void);
 int criu_restore_child(void);
 
@@ -279,6 +280,7 @@ void criu_local_set_notify_cb(criu_opts *opts, int (*cb)(char *action, criu_noti
 
 int criu_local_check(criu_opts *opts);
 int criu_local_dump(criu_opts *opts);
+int criu_local_pre_dump(criu_opts *opts);
 int criu_local_restore(criu_opts *opts);
 int criu_local_restore_child(criu_opts *opts);
 int criu_local_dump_iters(criu_opts *opts, int (*more)(criu_predump_info pi));
-- 
2.34.1