[CRIU] [PATCHv2 13/30] page-pipe: add compatible iovec

Dmitry Safonov dsafonov at virtuozzo.com
Fri Jun 24 08:08:18 PDT 2016


struct iovec may have different size for dumpee.
But that reason, pages dump will fail (with added debug to pie):
(00.011440) page-pipe: Page pipe:
(00.011441) page-pipe: * 1 pipes 8/523 iovs:
(00.011442) page-pipe: 	buf 16 pages, 8 iovs:
(00.011444) page-pipe: 		0x8048000 3
(00.011446) page-pipe: 		0xf7512000 1
(00.011447) page-pipe: 		0xf76ca000 4
(00.011449) page-pipe: 		0xf76cf000 1
(00.011450) page-pipe: 		0xf76dc000 2
(00.011452) page-pipe: 		0xf76e1000 1
(00.011454) page-pipe: 		0xf7702000 2
(00.011455) page-pipe: 		0xffdad000 2
(00.011470) page-pipe: * 0 holes:
(00.011471) PPB: 16 pages 8 segs 16 pipe 0 off
(00.011476) Sent msg to daemon 8 0 0
pie: __fetched msg: 8 0 0
(00.011479) Wait for ack 8 on daemon socket
pie: sys_vmsplice for 16 pages 8 segs 0 off
pie:  buf 16 pages, 8 iovs:
pie: 	0x8048000 0
pie: 	0x3000 0
pie: 	0xf7512000 0
pie: 	0x1000 0
pie: 	0xf76ca000 0
pie: 	0x4000 0
pie: 	0xf76cf000 0
pie: 	0x1000 0
pie: Error (pie/parasite.c:93): Can't splice pages to pipe (0/16)
pie: __sent ack msg: 8 8 -1

Cc: Cyrill Gorcunov <gorcunov at openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov at virtuozzo.com>
---
 criu/include/page-pipe.h        |  5 ++--
 criu/include/parasite-syscall.h |  1 +
 criu/mem.c                      |  4 +--
 criu/page-pipe.c                | 56 +++++++++++++++++++++++++++++++++++------
 criu/parasite-syscall.c         |  2 +-
 criu/shmem.c                    |  2 +-
 6 files changed, 56 insertions(+), 14 deletions(-)

diff --git a/criu/include/page-pipe.h b/criu/include/page-pipe.h
index 696dc9fa1141..19e7a898e77f 100644
--- a/criu/include/page-pipe.h
+++ b/criu/include/page-pipe.h
@@ -95,10 +95,11 @@ struct page_pipe {
 
 	bool chunk_mode;	/* Restrict the maximum buffer size of pipes
 				   and dump memory for a few iterations */
+	bool compat_iov;	/* Use compatible iovs (struct compat_iovec) */
 };
 
-extern struct page_pipe *create_page_pipe(unsigned int nr,
-					  struct iovec *, bool chunk_mode);
+extern struct page_pipe *create_page_pipe(unsigned int nr, struct iovec *,
+					bool chunk_mode, bool compat_iov);
 extern void destroy_page_pipe(struct page_pipe *p);
 extern int page_pipe_add_page(struct page_pipe *p, unsigned long addr,
 			      unsigned int flags);
diff --git a/criu/include/parasite-syscall.h b/criu/include/parasite-syscall.h
index 74156d4182f9..388f96545583 100644
--- a/criu/include/parasite-syscall.h
+++ b/criu/include/parasite-syscall.h
@@ -122,6 +122,7 @@ extern int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
 extern int __parasite_execute_syscall(struct parasite_ctl *ctl,
 		user_regs_struct_t *regs, const char *code_syscall);
 extern bool arch_can_dump_task(pid_t pid);
+extern bool seized_native(struct parasite_ctl *ctl);
 
 /*
  * The PTRACE_SYSCALL will trap task twice -- on
diff --git a/criu/mem.c b/criu/mem.c
index db61aedae4f2..0ddf7e5243d7 100644
--- a/criu/mem.c
+++ b/criu/mem.c
@@ -292,8 +292,8 @@ static int __parasite_dump_pages_seized(struct parasite_ctl *ctl,
 		return -1;
 
 	ret = -1;
-	pp = create_page_pipe(vma_area_list->priv_size,
-			      pargs_iovs(args), pp_ret == NULL);
+	pp = create_page_pipe(vma_area_list->priv_size, pargs_iovs(args),
+				pp_ret == NULL, !seized_native(ctl));
 	if (!pp)
 		goto out;
 
diff --git a/criu/page-pipe.c b/criu/page-pipe.c
index 5faf155825cf..c38b96e89407 100644
--- a/criu/page-pipe.c
+++ b/criu/page-pipe.c
@@ -100,6 +100,18 @@ static struct page_pipe_buf *ppb_alloc_resize(struct page_pipe *pp, int size)
 	return ppb;
 }
 
+/* XXX: move to arch-depended file, when non-x86 add support for compat mode */
+struct iovec_compat {
+	u32	iov_base;
+	u32	iov_len;
+};
+
+static inline void iov_init_compat(struct iovec_compat *iov, unsigned long addr)
+{
+	iov->iov_base = (u32)addr;
+	iov->iov_len = PAGE_SIZE;
+}
+
 static int page_pipe_grow(struct page_pipe *pp, unsigned int flags)
 {
 	struct page_pipe_buf *ppb;
@@ -125,8 +137,8 @@ out:
 	return 0;
 }
 
-struct page_pipe *create_page_pipe(unsigned int nr_segs,
-				   struct iovec *iovs, bool chunk_mode)
+struct page_pipe *create_page_pipe(unsigned int nr_segs, struct iovec *iovs,
+		bool chunk_mode, bool compat_iov)
 {
 	struct page_pipe *pp;
 
@@ -146,6 +158,7 @@ struct page_pipe *create_page_pipe(unsigned int nr_segs,
 		pp->holes = NULL;
 
 		pp->chunk_mode = chunk_mode;
+		pp->compat_iov = compat_iov;
 
 		if (page_pipe_grow(pp, 0))
 			return NULL;
@@ -213,7 +226,13 @@ static inline int try_add_page_to(struct page_pipe *pp, struct page_pipe_buf *pp
 
 	pr_debug("Add iov to page pipe (%u iovs, %u/%u total)\n",
 			ppb->nr_segs, pp->free_iov, pp->nr_iovs);
-	iov_init(&ppb->iov[ppb->nr_segs++], addr);
+	if (pp->compat_iov) {
+		struct iovec_compat *iovs = (void *)ppb->iov;
+
+		iov_init_compat(&iovs[ppb->nr_segs++], addr);
+	} else {
+		iov_init(&ppb->iov[ppb->nr_segs++], addr);
+	}
 	pp->free_iov++;
 	BUG_ON(pp->free_iov > pp->nr_iovs);
 out:
@@ -263,7 +282,13 @@ int page_pipe_add_hole(struct page_pipe *pp, unsigned long addr)
 			iov_grow_page(&pp->holes[pp->free_hole - 1], addr))
 		goto out;
 
-	iov_init(&pp->holes[pp->free_hole++], addr);
+	if (pp->compat_iov) {
+		struct iovec_compat *iovs = (void *)pp->holes;
+
+		iov_init_compat(&iovs[pp->free_hole++], addr);
+	} else {
+		iov_init(&pp->holes[pp->free_hole++], addr);
+	}
 out:
 	return 0;
 }
@@ -434,6 +459,7 @@ void debug_show_page_pipe(struct page_pipe *pp)
 	struct page_pipe_buf *ppb;
 	int i;
 	struct iovec *iov;
+	struct iovec_compat *iov_c;
 
 	if (pr_quelled(LOG_DEBUG))
 		return;
@@ -445,14 +471,28 @@ void debug_show_page_pipe(struct page_pipe *pp)
 		pr_debug("\tbuf %u pages, %u iovs, flags: %x :\n",
 			 ppb->pages_in, ppb->nr_segs, ppb->flags);
 		for (i = 0; i < ppb->nr_segs; i++) {
-			iov = &ppb->iov[i];
-			pr_debug("\t\t%p %lu\n", iov->iov_base, iov->iov_len / PAGE_SIZE);
+			if (pp->compat_iov) {
+				iov_c = (void *)ppb->iov;
+				pr_debug("\t\t%x %lu\n", iov_c[i].iov_base,
+						iov_c[i].iov_len / PAGE_SIZE);
+			} else {
+				iov = &ppb->iov[i];
+				pr_debug("\t\t%p %lu\n", iov->iov_base,
+						iov->iov_len / PAGE_SIZE);
+			}
 		}
 	}
 
 	pr_debug("* %u holes:\n", pp->free_hole);
 	for (i = 0; i < pp->free_hole; i++) {
-		iov = &pp->holes[i];
-		pr_debug("\t%p %lu\n", iov->iov_base, iov->iov_len / PAGE_SIZE);
+		if (pp->compat_iov) {
+			iov_c = (void *)pp->holes;
+			pr_debug("\t%x %lu\n", iov_c[i].iov_base,
+					iov_c[i].iov_len / PAGE_SIZE);
+		} else {
+			iov = &pp->holes[i];
+			pr_debug("\t%p %lu\n", iov->iov_base,
+					iov->iov_len / PAGE_SIZE);
+		}
 	}
 }
diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c
index a0f9462dcfa0..e6db4972333b 100644
--- a/criu/parasite-syscall.c
+++ b/criu/parasite-syscall.c
@@ -126,7 +126,7 @@ static int restore_thread_ctx(int pid, struct thread_ctx *ctx)
 	return ret;
 }
 
-static inline bool seized_native(struct parasite_ctl *ctl)
+bool seized_native(struct parasite_ctl *ctl)
 {
 	return user_regs_native(&ctl->orig.regs);
 }
diff --git a/criu/shmem.c b/criu/shmem.c
index f86a56af659d..9b57c90ef488 100644
--- a/criu/shmem.c
+++ b/criu/shmem.c
@@ -571,7 +571,7 @@ static int dump_one_shmem(struct shmem_info *si)
 	if (!iovs)
 		goto err_unmap;
 
-	pp = create_page_pipe((nrpages + 1) / 2, iovs, true);
+	pp = create_page_pipe((nrpages + 1) / 2, iovs, true, false);
 	if (!pp)
 		goto err_iovs;
 
-- 
2.9.0



More information about the CRIU mailing list