[CRIU] [PATCH] page-server: check that all data have been accepted

Andrey Vagin avagin at openvz.org
Wed Aug 7 09:08:28 EDT 2013


Currently criu sends data to the page server, but it doesn't get any
feedback, so it can't be sure that all data have been accepted.

This patch adds a flush command, which requires an answer from the page
server. This command is sent before disconnecting.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 cr-dump.c           |  6 ++++++
 include/page-xfer.h |  1 +
 page-xfer.c         | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 64 insertions(+)

diff --git a/cr-dump.c b/cr-dump.c
index 49677db..2de0311 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -1608,6 +1608,9 @@ int cr_pre_dump_tasks(pid_t pid)
 
 	ret = 0;
 err:
+	if (disconnect_from_page_server())
+		ret = -1;
+
 	pstree_switch_state(root_item,
 			ret ? TASK_ALIVE : opts.final_state);
 	free_pstree(root_item);
@@ -1726,6 +1729,9 @@ int cr_dump_tasks(pid_t pid)
 
 	fd_id_show_tree();
 err:
+	if (disconnect_from_page_server())
+		ret = -1;
+
 	close_cr_fdset(&glob_fdset);
 
 	if (!ret) {
diff --git a/include/page-xfer.h b/include/page-xfer.h
index 67a59ec..7d2284a 100644
--- a/include/page-xfer.h
+++ b/include/page-xfer.h
@@ -30,4 +30,5 @@ struct page_pipe;
 int page_xfer_dump_pages(struct page_xfer *, struct page_pipe *,
 		unsigned long off);
 int connect_to_page_server(void);
+int disconnect_from_page_server(void);
 #endif
diff --git a/page-xfer.c b/page-xfer.c
index 4efa20c..6098b92 100644
--- a/page-xfer.c
+++ b/page-xfer.c
@@ -21,6 +21,8 @@ struct page_server_iov {
 #define PS_IOV_HOLE	2
 #define PS_IOV_OPEN	3
 
+#define PS_IOV_FLUSH		0x1023
+
 #define PS_TYPE_BITS	8
 #define PS_TYPE_MASK	((1 << PS_TYPE_BITS) - 1)
 
@@ -145,6 +147,7 @@ static int page_server_hole(int sk, struct page_server_iov *pi)
 static int page_server_serve(int sk)
 {
 	int ret = -1;
+	bool flushed = false;
 
 	if (pipe(cxfer.p)) {
 		pr_perror("Can't make pipe for xfer");
@@ -168,6 +171,8 @@ static int page_server_serve(int sk)
 			break;
 		}
 
+		flushed = false;
+
 		switch (pi.cmd) {
 		case PS_IOV_OPEN:
 			ret = page_server_open(&pi);
@@ -178,6 +183,22 @@ static int page_server_serve(int sk)
 		case PS_IOV_HOLE:
 			ret = page_server_hole(sk, &pi);
 			break;
+		case PS_IOV_FLUSH:
+		{
+			int32_t status = 0;
+
+			/*
+			 * An answer must be sent back to inform another side,
+			 * that all data were received
+			 */
+			if (write(sk, &status, sizeof(status)) != sizeof(status)) {
+				pr_perror("Can't send the final package");
+				ret = -1;
+			}
+
+			flushed = true;
+			break;
+		}
 		default:
 			pr_err("Unknown command %u\n", pi.cmd);
 			ret = -1;
@@ -188,6 +209,11 @@ static int page_server_serve(int sk)
 			break;
 	}
 
+	if (!flushed) {
+		pr_err("The data were not flushed");
+		ret = -1;
+	}
+
 	page_server_close();
 	pr_info("Session over\n");
 
@@ -273,6 +299,37 @@ int connect_to_page_server(void)
 	return 0;
 }
 
+int disconnect_from_page_server(void)
+{
+	struct page_server_iov pi = { .cmd = PS_IOV_FLUSH };
+	int32_t status = -1;
+	int ret = -1;
+
+	if (!opts.use_page_server)
+		return 0;
+
+	if (page_server_sk == -1)
+		return 0;
+
+	pr_info("Disconnect from the page server %s:%u\n",
+			inet_ntoa(opts.ps_addr.sin_addr),
+			(int)ntohs(opts.ps_addr.sin_port));
+	if (write(page_server_sk, &pi, sizeof(pi)) != sizeof(pi)) {
+		pr_perror("Can't write the fini command to server");
+		goto out;
+	}
+
+	if (read(page_server_sk, &status, sizeof(status)) != sizeof(status)) {
+		pr_perror("The page server doesn't answer");
+		goto out;
+	}
+
+	ret = 0;
+out:
+	close_safe(&page_server_sk);
+	return ret ? : status;
+}
+
 static int write_pagemap_to_server(struct page_xfer *xfer,
 		struct iovec *iov)
 {
-- 
1.8.3.1



More information about the CRIU mailing list