[CRIU] [RFC PATCH 4/7] page-xfer: add methods for requesting and receiving remote pages

Mike Rapoport rppt at linux.vnet.ibm.com
Mon Nov 14 07:37:27 PST 2016


For asynchrounous page transfers in post-copy migration we need to be able
to request a remote pages, receive back information about the data is going
to arrive and receive the page data itself.

Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
 criu/include/page-xfer.h | 17 +++++++++++++++++
 criu/page-xfer.c         | 45 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 62 insertions(+)

diff --git a/criu/include/page-xfer.h b/criu/include/page-xfer.h
index fdda105..7cd0055 100644
--- a/criu/include/page-xfer.h
+++ b/criu/include/page-xfer.h
@@ -42,6 +42,23 @@ extern int disconnect_from_page_server(void);
 
 extern int check_parent_page_xfer(int fd_type, long id);
 
+/*
+ * The post-copy migration makes it necessary to receive pages from
+ * remote dump. The protocol we use for that is quite simple:
+ * - lazy-pages sedns request containing PS_IOV_GET(nr_pages, vaddr, pid)
+ * - dump-side page server responds with PS_IOV_ADD(nr_pages, vaddr,
+     pid) or PS_IOV_ADD(0, 0, 0) if it failed to locate the required
+     pages
+ * - dump-side page server sends the raw page data
+ */
+
+/* sync receive of remote pages */
 extern int get_remote_pages(int pid, unsigned long addr, int nr_pages, void *dest);
 
+/* async request/receive of remote pages */
+extern int request_remote_pages(int pid, unsigned long addr, int nr_pages);
+extern int receive_remote_pages_info(int *nr_pages, unsigned long *addr, int *pid);
+extern int receive_remote_pages(int len, void *buf);
+
+
 #endif /* __CR_PAGE_XFER__H__ */
diff --git a/criu/page-xfer.c b/criu/page-xfer.c
index b509136..6956f2b 100644
--- a/criu/page-xfer.c
+++ b/criu/page-xfer.c
@@ -916,3 +916,48 @@ int get_remote_pages(int pid, unsigned long addr, int nr_pages, void *dest)
 
 	return 1;
 }
+
+int request_remote_pages(int pid, unsigned long addr, int nr_pages)
+{
+	struct page_server_iov pi = {
+		.cmd		= PS_IOV_GET,
+		.nr_pages	= nr_pages,
+		.vaddr		= addr,
+		.dst_id		= pid,
+	};
+
+	/* We cannot use send_psi here because we have to use MSG_DONTWAIT */
+	if (send(page_server_sk, &pi, sizeof(pi), MSG_DONTWAIT) != sizeof(pi)) {
+		pr_perror("Can't write PSI to server");
+		return -1;
+	}
+
+	tcp_nodelay(page_server_sk, true);
+	return 0;
+}
+
+int receive_remote_pages_info(int *nr_pages, unsigned long *addr, int *pid)
+{
+	struct page_server_iov pi;
+
+	if (recv(page_server_sk, &pi, sizeof(pi), MSG_WAITALL) != sizeof(pi)) {
+		pr_perror("Failed to receive page metadata");
+		return -1;
+	}
+
+	*nr_pages = pi.nr_pages;
+	*addr = pi.vaddr;
+	*pid = pi.dst_id;
+
+	return 0;
+}
+
+int receive_remote_pages(int len, void *buf)
+{
+	if (recv(page_server_sk, buf, len, MSG_WAITALL) != len) {
+		pr_perror("Failed to receive page data");
+		return -1;
+	}
+
+	return 0;
+}
-- 
1.9.1



More information about the CRIU mailing list