[CRIU] [PATCH v5 6/8] criu: add ability to skip writing lazy pages

Mike Rapoport rppt at linux.vnet.ibm.com
Tue Jun 28 22:55:11 PDT 2016


When appropriate, the lazy pages will no be written to the destination.
Instead, a pagemap entry for range of such pages will be marked with 'lazy'
flag.

Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
 criu/cr-dump.c           |  2 +-
 criu/include/page-xfer.h |  2 +-
 criu/include/stats.h     |  1 +
 criu/mem.c               | 16 ++++++++++------
 criu/page-xfer.c         | 14 +++++++++++++-
 criu/pagemap.c           |  2 +-
 criu/shmem.c             |  2 +-
 criu/stats.c             |  1 +
 images/pagemap.proto     |  1 +
 images/stats.proto       |  1 +
 10 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/criu/cr-dump.c b/criu/cr-dump.c
index 33355fb..ddd64cd 100644
--- a/criu/cr-dump.c
+++ b/criu/cr-dump.c
@@ -1429,7 +1429,7 @@ static int cr_pre_dump_finish(int ret)
 		if (ret < 0)
 			goto err;
 
-		ret = page_xfer_dump_pages(&xfer, ctl->mem_pp, 0);
+		ret = page_xfer_dump_pages(&xfer, ctl->mem_pp, 0, true);
 
 		xfer.close(&xfer);
 
diff --git a/criu/include/page-xfer.h b/criu/include/page-xfer.h
index 3ba61ed..f92d357 100644
--- a/criu/include/page-xfer.h
+++ b/criu/include/page-xfer.h
@@ -38,7 +38,7 @@ struct page_xfer {
 extern int open_page_xfer(struct page_xfer *xfer, int fd_type, long id);
 struct page_pipe;
 extern int page_xfer_dump_pages(struct page_xfer *, struct page_pipe *,
-				unsigned long off);
+				unsigned long off, bool dump_lazy);
 extern int connect_to_page_server(void);
 extern int disconnect_from_page_server(void);
 
diff --git a/criu/include/stats.h b/criu/include/stats.h
index c0effa7..5d71778 100644
--- a/criu/include/stats.h
+++ b/criu/include/stats.h
@@ -26,6 +26,7 @@ enum {
 	CNT_PAGES_SKIPPED_PARENT,
 	CNT_PAGES_WRITTEN,
 	CNT_PAGES_ZERO,
+	CNT_PAGES_LAZY,
 
 	DUMP_CNT_NR_STATS,
 };
diff --git a/criu/mem.c b/criu/mem.c
index c4af568..897c48b 100644
--- a/criu/mem.c
+++ b/criu/mem.c
@@ -141,7 +141,7 @@ static int generate_iovs(struct vma_area *vma, struct page_pipe *pp, u64 *map, u
 {
 	u64 *at = &map[PAGE_PFN(*off)];
 	unsigned long pfn, nr_to_scan;
-	unsigned long pages[3] = {};
+	unsigned long pages[4] = {};
 
 	nr_to_scan = (vma_area_len(vma) - *off) / PAGE_SIZE;
 
@@ -173,7 +173,10 @@ static int generate_iovs(struct vma_area *vma, struct page_pipe *pp, u64 *map, u
 			pages[1]++;
 		} else {
 			ret = page_pipe_add_page(pp, vaddr, ppb_flags);
-			pages[2]++;
+			if (ppb_flags & PPB_LAZY)
+				pages[2]++;
+			else
+				pages[3]++;
 		}
 
 		if (ret) {
@@ -187,10 +190,11 @@ static int generate_iovs(struct vma_area *vma, struct page_pipe *pp, u64 *map, u
 	cnt_add(CNT_PAGES_SCANNED, nr_to_scan);
 	cnt_add(CNT_PAGES_SKIPPED_PARENT, pages[0]);
 	cnt_add(CNT_PAGES_ZERO, pages[1]);
-	cnt_add(CNT_PAGES_WRITTEN, pages[2]);
+	cnt_add(CNT_PAGES_LAZY, pages[2]);
+	cnt_add(CNT_PAGES_WRITTEN, pages[3]);
 
-	pr_info("Pagemap generated: %lu pages %lu zeros %lu holes\n",
-		pages[2], pages[1], pages[0]);
+	pr_info("Pagemap generated: %lu pages (%lu lazy) %lu zeros %lu holes\n",
+		pages[3] + pages[2], pages[2], pages[1], pages[0]);
 	return 0;
 }
 
@@ -264,7 +268,7 @@ static int dump_pages(struct page_pipe *pp, struct parasite_ctl *ctl,
 	 */
 	if (xfer) {
 		timing_start(TIME_MEMWRITE);
-		ret = page_xfer_dump_pages(xfer, pp, 0);
+		ret = page_xfer_dump_pages(xfer, pp, 0, true);
 		timing_stop(TIME_MEMWRITE);
 	}
 
diff --git a/criu/page-xfer.c b/criu/page-xfer.c
index 1164efc..afbaeb5 100644
--- a/criu/page-xfer.c
+++ b/criu/page-xfer.c
@@ -38,6 +38,7 @@ static void psi2iovec(struct page_server_iov *ps, struct iovec *iov)
 #define PS_IOV_OPEN2	4
 #define PS_IOV_PARENT	5
 #define PS_IOV_ZERO	6
+#define PS_IOV_LAZY	7
 
 #define PS_IOV_FLUSH		0x1023
 #define PS_IOV_FLUSH_N_CLOSE	0x1024
@@ -251,6 +252,10 @@ static int write_hole_loc(struct page_xfer *xfer, struct iovec *iov, int type)
 		pe.has_zero = true;
 		pe.zero = true;
 		break;
+	case PS_IOV_LAZY:
+		pe.has_lazy = true;
+		pe.lazy = true;
+		break;
 	default:
 		return -1;
 	}
@@ -365,7 +370,7 @@ static int dump_holes(struct page_xfer *xfer, struct page_pipe *pp,
 }
 
 int page_xfer_dump_pages(struct page_xfer *xfer, struct page_pipe *pp,
-		unsigned long off)
+			 unsigned long off, bool dump_lazy)
 {
 	struct page_pipe_buf *ppb;
 
@@ -387,6 +392,12 @@ int page_xfer_dump_pages(struct page_xfer *xfer, struct page_pipe *pp,
 			pr_debug("\tp %p [%u]\n", iov->iov_base,
 					(unsigned int)(iov->iov_len / PAGE_SIZE));
 
+			if (!dump_lazy && ppb->flags & PPB_LAZY) {
+				if (xfer->write_hole(xfer, iov, PS_IOV_LAZY))
+					return -1;
+				continue;
+			}
+
 			if (xfer->write_pagemap(xfer, iov))
 				return -1;
 			if (xfer->write_pages(xfer, ppb->p[0], iov->iov_len))
@@ -641,6 +652,7 @@ static int page_server_serve(int sk)
 			break;
 		case PS_IOV_HOLE:
 		case PS_IOV_ZERO:
+		case PS_IOV_LAZY:
 			ret = page_server_hole(sk, &pi);
 			break;
 		case PS_IOV_FLUSH:
diff --git a/criu/pagemap.c b/criu/pagemap.c
index 2416259..0b9d95b 100644
--- a/criu/pagemap.c
+++ b/criu/pagemap.c
@@ -160,7 +160,7 @@ static void skip_pagemap_pages(struct page_read *pr, unsigned long len)
 		return;
 
 	pr_debug("\tpr%u Skip %lu bytes from page-dump\n", pr->id, len);
-	if (!pr->pe->in_parent && !pr->pe->zero)
+	if (!pr->pe->in_parent && !pr->pe->zero && !pr->pe->lazy)
 		pr->pi_off += len;
 	pr->cvaddr += len;
 }
diff --git a/criu/shmem.c b/criu/shmem.c
index ecedffb..67bce76 100644
--- a/criu/shmem.c
+++ b/criu/shmem.c
@@ -524,7 +524,7 @@ static int dump_pages(struct page_pipe *pp, struct page_xfer *xfer, void *addr)
 			return -1;
 		}
 
-	return page_xfer_dump_pages(xfer, pp, (unsigned long)addr);
+	return page_xfer_dump_pages(xfer, pp, (unsigned long)addr, true);
 }
 
 static int dump_one_shmem(struct shmem_info *si)
diff --git a/criu/stats.c b/criu/stats.c
index c01e010..a575e77 100644
--- a/criu/stats.c
+++ b/criu/stats.c
@@ -123,6 +123,7 @@ void write_stats(int what)
 		ds_entry.pages_skipped_parent = dstats->counts[CNT_PAGES_SKIPPED_PARENT];
 		ds_entry.pages_written = dstats->counts[CNT_PAGES_WRITTEN];
 		ds_entry.pages_zero = dstats->counts[CNT_PAGES_ZERO];
+		ds_entry.pages_lazy = dstats->counts[CNT_PAGES_LAZY];
 
 		name = "dump";
 	} else if (what == RESTORE_STATS) {
diff --git a/images/pagemap.proto b/images/pagemap.proto
index f80afeb..5287da9 100644
--- a/images/pagemap.proto
+++ b/images/pagemap.proto
@@ -9,4 +9,5 @@ message pagemap_entry {
 	required uint32 nr_pages	= 2;
 	optional bool	in_parent	= 3;
 	optional bool	zero		= 4;
+	optional bool	lazy		= 5;
 }
diff --git a/images/stats.proto b/images/stats.proto
index 307bb29..1e5848a 100644
--- a/images/stats.proto
+++ b/images/stats.proto
@@ -12,6 +12,7 @@ message dump_stats_entry {
 	optional uint32			irmap_resolve		= 8;
 
 	required uint64			pages_zero		= 9;
+	required uint64			pages_lazy		= 10;
 }
 
 message restore_stats_entry {
-- 
1.9.1



More information about the CRIU mailing list