[CRIU] [RFC PATCH 2/3] page-xfer: add ability to send pages from local dump
Mike Rapoport
rppt at linux.vnet.ibm.com
Mon Nov 21 06:16:46 PST 2016
Currently, standalone page-server can only receive pages from the remote
dump. Extend it with the ability to serve local memory dump to a remote
lazy-pages daemon.
Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
criu/page-xfer.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 104 insertions(+), 1 deletion(-)
diff --git a/criu/page-xfer.c b/criu/page-xfer.c
index 234c38d..b6c10d9 100644
--- a/criu/page-xfer.c
+++ b/criu/page-xfer.c
@@ -19,6 +19,7 @@
#include "fcntl.h"
#include "pstree.h"
#include "parasite-syscall.h"
+#include "rst_info.h"
static int page_server_sk = -1;
@@ -789,14 +790,116 @@ static int page_server_serve(int sk)
return ret;
}
+static int fill_page_pipe(struct page_read *pr, struct page_pipe *pp)
+{
+ struct page_pipe_buf *ppb;
+ int i, ret;
+
+ pr->reset(pr);
+
+ while (pr->advance(pr)) {
+ unsigned long vaddr = pr->pe->vaddr;
+
+ for (i = 0; i < pr->pe->nr_pages; i++, vaddr += PAGE_SIZE) {
+ if (pagemap_zero(pr->pe))
+ ret = page_pipe_add_hole(pp, vaddr, PP_HOLE_ZERO);
+ else if (pagemap_in_parent(pr->pe))
+ ret = page_pipe_add_hole(pp, vaddr, PP_HOLE_PARENT);
+ else
+ ret = page_pipe_add_page(pp, vaddr, pagemap_lazy(pr->pe) ? PPB_LAZY : 0);
+ if (ret) {
+ pr_err("add page at %lx\n", vaddr);
+ return -1;
+ }
+ }
+ }
+
+ list_for_each_entry(ppb, &pp->bufs, l) {
+ for (i = 0; i < ppb->nr_segs; i++) {
+ struct iovec iov = get_iov(ppb->iov, i,
+ pp->flags & PP_COMPAT);
+ if (splice(img_raw_fd(pr->pi), NULL, ppb->p[1], NULL,
+ iov.iov_len, SPLICE_F_MOVE) != iov.iov_len) {
+ pr_perror("splice");
+ return -1;
+ }
+ }
+ }
+
+ debug_show_page_pipe(pp);
+
+ return 0;
+}
+
+static int page_pipe_from_pagemap(struct page_pipe **pp, int pid)
+{
+ struct page_read pr;
+ int nr_pages = 0;
+
+ if (open_page_read(pid, &pr, PR_TASK) <= 0) {
+ pr_err("Failed to open page read for %d\n", pid);
+ return -1;
+ }
+
+ while (pr.advance(&pr))
+ if (pagemap_present(pr.pe))
+ nr_pages += pr.pe->nr_pages;
+
+ *pp = create_page_pipe(nr_pages, NULL, 0);
+ if (!*pp) {
+ pr_err("Cannot create page pipe for %d\n", pid);
+ return -1;
+ }
+
+ if (fill_page_pipe(&pr, *pp))
+ return -1;
+
+ return 0;
+}
+
+static int page_server_init_send(void)
+{
+ struct pstree_item *pi;
+ struct page_pipe *pp;
+
+ BUILD_BUG_ON(sizeof(struct dmp_info) > sizeof(struct rst_info));
+
+ if (prepare_dummy_pstree())
+ return -1;
+
+ for_each_pstree_item(pi) {
+ if (!task_alive(pi))
+ continue;
+
+ if (page_pipe_from_pagemap(&pp, pi->pid.virt)) {
+ pr_err("open_page_read\n");
+ return -1;
+ }
+
+ /*
+ * prepare_dummy_pstree presumes 'restore' behaviour,
+ * but page_server_get_pages uses dmpi() to get access
+ * to the page-pipe, so we are faking it here.
+ */
+ memset(rsti(pi), 0, sizeof(struct rst_info));
+ dmpi(pi)->mem_pp = pp;
+ }
+
+ return 0;
+}
+
int cr_page_server(bool daemon_mode, int cfd)
{
int ask = -1;
int sk = -1;
int ret;
- if (!opts.lazy_pages)
+ if (!opts.lazy_pages) {
up_page_ids_base();
+ } else {
+ if (page_server_init_send())
+ return -1;
+ }
if (opts.ps_socket != -1) {
ret = 0;
--
1.9.1
More information about the CRIU
mailing list