[CRIU] [PATCH v3 02/11] criu: page_pipe_buf: add PPB_LAZY flag

Mike Rapoport rapoport at linux.vnet.ibm.com
Tue May 31 14:01:35 PDT 2016


From: Mike Rapoport <rppt at linux.vnet.ibm.com>

for buffers that contain potentially lazy pages

Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
 criu/include/page-pipe.h |  5 ++++-
 criu/mem.c               |  6 +++++-
 criu/page-pipe.c         | 35 +++++++++++++++++++++--------------
 criu/shmem.c             |  2 +-
 4 files changed, 31 insertions(+), 17 deletions(-)

diff --git a/criu/include/page-pipe.h b/criu/include/page-pipe.h
index a2dc268..031f145 100644
--- a/criu/include/page-pipe.h
+++ b/criu/include/page-pipe.h
@@ -74,6 +74,8 @@ struct page_pipe_buf {
 	unsigned int pipe_size;	/* how many pages can be fit into pipe */
 	unsigned int pages_in;	/* how many pages are there */
 	unsigned int nr_segs;	/* how many iov-s are busy */
+#define PPB_LAZY (1 << 0)
+	unsigned int flags;
 	struct iovec *iov;	/* vaddr:len map */
 	struct list_head l;	/* links into page_pipe->bufs */
 };
@@ -98,7 +100,8 @@ struct page_pipe {
 extern struct page_pipe *create_page_pipe(unsigned int nr,
 					  struct iovec *, bool chunk_mode);
 extern void destroy_page_pipe(struct page_pipe *p);
-extern int page_pipe_add_page(struct page_pipe *p, unsigned long addr);
+extern int page_pipe_add_page(struct page_pipe *p, unsigned long addr,
+			      unsigned int flags);
 extern int page_pipe_add_hole(struct page_pipe *p, unsigned long addr);
 
 extern void debug_show_page_pipe(struct page_pipe *pp);
diff --git a/criu/mem.c b/criu/mem.c
index fbcc77d..a44ad69 100644
--- a/criu/mem.c
+++ b/criu/mem.c
@@ -142,6 +142,7 @@ static int generate_iovs(struct vma_area *vma, struct page_pipe *pp, u64 *map, u
 
 	for (pfn = 0; pfn < nr_to_scan; pfn++) {
 		unsigned long vaddr;
+		unsigned int ppb_flags = 0;
 		int ret;
 
 		if (!should_dump_page(vma->e, at[pfn]))
@@ -149,6 +150,9 @@ static int generate_iovs(struct vma_area *vma, struct page_pipe *pp, u64 *map, u
 
 		vaddr = vma->e->start + *off + pfn * PAGE_SIZE;
 
+		if (vma_entry_can_be_lazy(vma->e))
+			ppb_flags |= PPB_LAZY;
+
 		/*
 		 * If we're doing incremental dump (parent images
 		 * specified) and page is not soft-dirty -- we dump
@@ -160,7 +164,7 @@ static int generate_iovs(struct vma_area *vma, struct page_pipe *pp, u64 *map, u
 			ret = page_pipe_add_hole(pp, vaddr);
 			pages[0]++;
 		} else {
-			ret = page_pipe_add_page(pp, vaddr);
+			ret = page_pipe_add_page(pp, vaddr, ppb_flags);
 			pages[1]++;
 		}
 
diff --git a/criu/page-pipe.c b/criu/page-pipe.c
index aad5905..ccafea0 100644
--- a/criu/page-pipe.c
+++ b/criu/page-pipe.c
@@ -55,10 +55,12 @@ static void ppb_destroy(struct page_pipe_buf *ppb)
 }
 
 static void ppb_init(struct page_pipe_buf *ppb, unsigned int pages_in,
-		     unsigned int nr_segs, struct iovec *iov)
+		     unsigned int nr_segs, unsigned int flags,
+		     struct iovec *iov)
 {
 	ppb->pages_in = pages_in;
 	ppb->nr_segs = nr_segs;
+	ppb->flags = flags;
 	ppb->iov = iov;
 }
 
@@ -79,7 +81,7 @@ static int ppb_resize_pipe(struct page_pipe_buf *ppb, unsigned long new_size)
 	return 0;
 }
 
-static int page_pipe_grow(struct page_pipe *pp)
+static int page_pipe_grow(struct page_pipe *pp, unsigned int flags)
 {
 	struct page_pipe_buf *ppb;
 
@@ -99,7 +101,7 @@ static int page_pipe_grow(struct page_pipe *pp)
 		return -1;
 
 out:
-	ppb_init(ppb, 0, 0, &pp->iovs[pp->free_iov]);
+	ppb_init(ppb, 0, 0, flags, &pp->iovs[pp->free_iov]);
 
 	return 0;
 }
@@ -126,7 +128,7 @@ struct page_pipe *create_page_pipe(unsigned int nr_segs,
 
 		pp->chunk_mode = chunk_mode;
 
-		if (page_pipe_grow(pp))
+		if (page_pipe_grow(pp, 0))
 			return NULL;
 	}
 
@@ -159,13 +161,16 @@ void page_pipe_reinit(struct page_pipe *pp)
 
 	pp->free_hole = 0;
 
-	if (page_pipe_grow(pp))
+	if (page_pipe_grow(pp, 0))
 		BUG(); /* It can't fail, because ppb is in free_bufs */
 }
 
 static inline int try_add_page_to(struct page_pipe *pp, struct page_pipe_buf *ppb,
-		unsigned long addr)
+		unsigned long addr, unsigned int flags)
 {
+	if (ppb->flags != flags)
+		return 1;
+
 	if (ppb->pages_in == ppb->pipe_size) {
 		unsigned long new_size = ppb->pipe_size << 1;
 		int ret;
@@ -197,25 +202,27 @@ out:
 	return 0;
 }
 
-static inline int try_add_page(struct page_pipe *pp, unsigned long addr)
+static inline int try_add_page(struct page_pipe *pp, unsigned long addr,
+			       unsigned int flags)
 {
 	BUG_ON(list_empty(&pp->bufs));
-	return try_add_page_to(pp, list_entry(pp->bufs.prev, struct page_pipe_buf, l), addr);
+	return try_add_page_to(pp, list_entry(pp->bufs.prev, struct page_pipe_buf, l), addr, flags);
 }
 
-int page_pipe_add_page(struct page_pipe *pp, unsigned long addr)
+int page_pipe_add_page(struct page_pipe *pp, unsigned long addr,
+		       unsigned int flags)
 {
 	int ret;
 
-	ret = try_add_page(pp, addr);
+	ret = try_add_page(pp, addr, flags);
 	if (ret <= 0)
 		return ret;
 
-	ret = page_pipe_grow(pp);
+	ret = page_pipe_grow(pp, flags);
 	if (ret < 0)
 		return ret;
 
-	ret = try_add_page(pp, addr);
+	ret = try_add_page(pp, addr, flags);
 	BUG_ON(ret > 0);
 	return ret;
 }
@@ -255,8 +262,8 @@ void debug_show_page_pipe(struct page_pipe *pp)
 	pr_debug("* %u pipes %u/%u iovs:\n",
 			pp->nr_pipes, pp->free_iov, pp->nr_iovs);
 	list_for_each_entry(ppb, &pp->bufs, l) {
-		pr_debug("\tbuf %u pages, %u iovs:\n",
-				ppb->pages_in, ppb->nr_segs);
+		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);
diff --git a/criu/shmem.c b/criu/shmem.c
index b017a7c..18acd15 100644
--- a/criu/shmem.c
+++ b/criu/shmem.c
@@ -598,7 +598,7 @@ static int dump_one_shmem(struct shmem_info *si)
 		if (!(map[pfn] & PAGE_RSS))
 			continue;
 again:
-		ret = page_pipe_add_page(pp, (unsigned long)addr + pfn * PAGE_SIZE);
+		ret = page_pipe_add_page(pp, (unsigned long)addr + pfn * PAGE_SIZE, 0);
 		if (ret == -EAGAIN) {
 			ret = dump_pages(pp, &xfer, addr);
 			if (ret)
-- 
1.9.1



More information about the CRIU mailing list