[CRIU] [PATCH 5/6] criu: pagemap: add PE_PRESENT flag

Mike Rapoport rppt at linux.vnet.ibm.com
Thu Sep 8 00:39:11 PDT 2016


The PE_PRESENT flags is always set for pagemap entries that have
corresponding pages in the pages*img. Pagemap entries describing a hole
either with zero page or with pages in the parent snapshot will no have
PE_PRESENT flag set.
Pagemap entry that may be lazily restored is a special case. For the lazy
restore from disk case, both PE_LAZY and PE_PRESENT will be set in the
pagemap, but for the remote lazy pages case only PE_LAZY will be set.

Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
 criu/include/pagemap.h |  6 ++++++
 criu/page-xfer.c       | 16 +++++++++++-----
 criu/pagemap.c         | 10 +++++++++-
 3 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/criu/include/pagemap.h b/criu/include/pagemap.h
index f4a9285..705a9af 100644
--- a/criu/include/pagemap.h
+++ b/criu/include/pagemap.h
@@ -97,6 +97,7 @@ extern int dedup_one_iovec(struct page_read *pr, struct iovec *iov);
 #define PE_PARENT	(1 << 0)	/* pages are in parent snapshot */
 #define PE_ZERO		(1 << 1)	/* pages can be lazily restored */
 #define PE_LAZY		(1 << 2)	/* pages are mapped to zero pfn */
+#define PE_PRESENT	(1 << 3)	/* pages are present in pages*img */
 
 static inline bool pagemap_in_parent(PagemapEntry *pe)
 {
@@ -113,4 +114,9 @@ static inline bool pagemap_lazy(PagemapEntry *pe)
 	return !!(pe->flags & PE_LAZY);
 }
 
+static inline bool pagemap_present(PagemapEntry *pe)
+{
+	return !!(pe->flags & PE_PRESENT);
+}
+
 #endif /* __CR_PAGE_READ_H__ */
diff --git a/criu/page-xfer.c b/criu/page-xfer.c
index 68dba86..798ea0b 100644
--- a/criu/page-xfer.c
+++ b/criu/page-xfer.c
@@ -440,6 +440,7 @@ int page_xfer_dump_pages(struct page_xfer *xfer, struct page_pipe *pp,
 
 		for (i = 0; i < ppb->nr_segs; i++) {
 			struct iovec iov = get_iov(ppb->iov, i, pp->flags & PP_COMPAT);
+			u32 flags = PE_PRESENT;
 
 			ret = dump_holes(xfer, pp, &cur_hole, iov.iov_base, off);
 			if (ret)
@@ -450,13 +451,18 @@ 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 (ppb->flags & PPB_LAZY) {
+				if (!dump_lazy) {
+					if (xfer->write_hole(xfer, &iov,
+							     PS_IOV_LAZY))
+						return -1;
+					continue;
+				} else {
+					flags |= PE_LAZY;
+				}
 			}
 
-			if (xfer->write_pagemap(xfer, &iov, 0))
+			if (xfer->write_pagemap(xfer, &iov, flags))
 				return -1;
 			if (xfer->write_pages(xfer, ppb->p[0], iov.iov_len))
 				return -1;
diff --git a/criu/pagemap.c b/criu/pagemap.c
index aaef5a4..71ae11e 100644
--- a/criu/pagemap.c
+++ b/criu/pagemap.c
@@ -158,7 +158,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 (!pagemap_in_parent(pr->pe) && !pagemap_zero(pr->pe) && !pagemap_lazy(pr->pe))
+	if (pagemap_present(pr->pe))
 		pr->pi_off += len;
 	pr->cvaddr += len;
 }
@@ -360,8 +360,16 @@ err_cl:
 
 static void init_compat_pagemap_entry(PagemapEntry *pe)
 {
+	/*
+	 * pagemap image generated with older version will either
+	 * contain a hole because the pages are in the parent
+	 * shanpshot or a pagemap that should be marked with
+	 * PE_PRESENT
+	 */
 	if (pe->has_in_parent && pe->in_parent)
 		pe->flags |= PE_PARENT;
+	else if (!pe->has_flags)
+		pe->flags = PE_PRESENT;
 }
 
 /*
-- 
1.9.1



More information about the CRIU mailing list