[CRIU] [PATCH] service: Add ability to inherit page server socket

Pavel Emelyanov xemul at parallels.com
Mon Sep 1 13:45:03 PDT 2014


The swrk action is turning out to be a cool thing. We can
spawn criu with swrk action with some FD being open, then
ask for dump/pre-dump/page-server telling it that some
descriptor it needs is "out there".

This patch lets us specify that the page server communication
channel is already in criu's fdtable.

TODO: teach regular service to accept fd via service socket.

Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
---
 cr-service.c         |  7 +++++++
 crtools.c            |  1 +
 include/cr_options.h |  1 +
 page-xfer.c          | 42 +++++++++++++++++++++++++++++++++++-------
 protobuf/rpc.proto   |  1 +
 5 files changed, 45 insertions(+), 7 deletions(-)

diff --git a/cr-service.c b/cr-service.c
index d5a4737..9f7873b 100644
--- a/cr-service.c
+++ b/cr-service.c
@@ -278,6 +278,13 @@ static int setup_opts_from_req(int sk, CriuOpts *req)
 		opts.use_page_server = true;
 		opts.addr = req->ps->address;
 		opts.ps_port = htons((short)req->ps->port);
+
+		if (req->ps->has_fd) {
+			if (!opts.swrk_restore)
+				return -1;
+
+			opts.ps_socket = req->ps->fd;
+		}
 	}
 
 	if (req->notify_scripts) {
diff --git a/crtools.c b/crtools.c
index fa1d375..21ca63a 100644
--- a/crtools.c
+++ b/crtools.c
@@ -52,6 +52,7 @@ void init_opts(void)
 
 	opts.cpu_cap = CPU_CAP_ALL;
 	opts.manage_cgroups = false;
+	opts.ps_socket = -1;
 }
 
 static int parse_ns_string(const char *ptr)
diff --git a/include/cr_options.h b/include/cr_options.h
index d715773..b603804 100644
--- a/include/cr_options.h
+++ b/include/cr_options.h
@@ -51,6 +51,7 @@ struct cr_options {
 	bool			use_page_server;
 	unsigned short		ps_port;
 	char			*addr;
+	int			ps_socket;
 	bool			track_mem;
 	char			*img_parent;
 	bool			auto_dedup;
diff --git a/page-xfer.c b/page-xfer.c
index c71ca51..54340b1 100644
--- a/page-xfer.c
+++ b/page-xfer.c
@@ -40,6 +40,7 @@ static int open_page_local_xfer(struct page_xfer *xfer, int fd_type, long id);
 #define PS_IOV_OPEN	3
 
 #define PS_IOV_FLUSH		0x1023
+#define PS_IOV_FLUSH_N_CLOSE	0x1024
 
 #define PS_TYPE_BITS	8
 #define PS_TYPE_MASK	((1 << PS_TYPE_BITS) - 1)
@@ -198,6 +199,7 @@ static int page_server_serve(int sk)
 			ret = page_server_hole(sk, &pi);
 			break;
 		case PS_IOV_FLUSH:
+		case PS_IOV_FLUSH_N_CLOSE:
 		{
 			int32_t status = 0;
 
@@ -220,7 +222,7 @@ static int page_server_serve(int sk)
 			break;
 		}
 
-		if (ret)
+		if (ret || (pi.cmd == PS_IOV_FLUSH_N_CLOSE))
 			break;
 	}
 
@@ -254,12 +256,19 @@ static int get_sockaddr_in(struct sockaddr_in *addr)
 
 int cr_page_server(bool daemon_mode)
 {
-	int sk, ask = -1, ret;
+	int sk = -1, ask = -1, ret;
 	struct sockaddr_in saddr, caddr;
 	socklen_t clen = sizeof(caddr);
 
 	up_page_ids_base();
 
+	if (opts.ps_socket != -1) {
+		ret = 0;
+		ask = opts.ps_socket;
+		pr_info("Re-using ps socket %d\n", ask);
+		goto no_server;
+	}
+
 	pr_info("Starting page server on port %u\n", (int)ntohs(opts.ps_port));
 
 	sk = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
@@ -281,6 +290,7 @@ int cr_page_server(bool daemon_mode)
 		goto out;
 	}
 
+no_server:
 	if (daemon_mode) {
 		ret = cr_daemon(1, 0);
 		if (ret == -1) {
@@ -298,11 +308,13 @@ int cr_page_server(bool daemon_mode)
 		}
 	}
 
-	ret = ask = accept(sk, (struct sockaddr *)&caddr, &clen);
-	if (ask < 0)
-		pr_perror("Can't accept connection to server");
+	if (sk >= 0) {
+		ret = ask = accept(sk, (struct sockaddr *)&caddr, &clen);
+		if (ask < 0)
+			pr_perror("Can't accept connection to server");
 
-	close(sk);
+		close(sk);
+	}
 
 	if (ask >= 0) {
 		pr_info("Accepted connection from %s:%u\n",
@@ -331,6 +343,12 @@ int connect_to_page_server(void)
 	if (!opts.use_page_server)
 		return 0;
 
+	if (opts.ps_socket != -1) {
+		page_server_sk = opts.ps_socket;
+		pr_info("Re-using ps socket %d\n", page_server_sk);
+		return 0;
+	}
+
 	pr_info("Connecting to server %s:%u\n",
 			opts.addr, (int)ntohs(opts.ps_port));
 
@@ -353,7 +371,7 @@ int connect_to_page_server(void)
 
 int disconnect_from_page_server(void)
 {
-	struct page_server_iov pi = { .cmd = PS_IOV_FLUSH };
+	struct page_server_iov pi = { };
 	int32_t status = -1;
 	int ret = -1;
 
@@ -366,6 +384,16 @@ int disconnect_from_page_server(void)
 	pr_info("Disconnect from the page server %s:%u\n",
 			opts.addr, (int)ntohs(opts.ps_port));
 
+	if (opts.ps_socket != -1)
+		/*
+		 * The socket might not get closed (held by
+		 * the parent process) so we must order the
+		 * page-server to terminate itself.
+		 */
+		pi.cmd = PS_IOV_FLUSH_N_CLOSE;
+	else
+		pi.cmd = PS_IOV_FLUSH;
+
 	if (write(page_server_sk, &pi, sizeof(pi)) != sizeof(pi)) {
 		pr_perror("Can't write the fini command to server");
 		goto out;
diff --git a/protobuf/rpc.proto b/protobuf/rpc.proto
index 46fba60..e9a74b4 100644
--- a/protobuf/rpc.proto
+++ b/protobuf/rpc.proto
@@ -2,6 +2,7 @@ message criu_page_server_info {
 	optional string		address	= 1;
 	optional int32		port	= 2;
 	optional int32		pid	= 3;
+	optional int32		fd	= 4;
 }
 
 message criu_veth_pair {
-- 
1.8.4.2



More information about the CRIU mailing list