[CRIU] [PATCH 3/6] criu: pagemap: replace 'zero' and 'lazy' booleans with 'flags'

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


Having three booleans in pagemap entry clues for usage of good old flags.
Replace 'zero' and 'lazy' booleans with flags and use flags for internal
tracking of in_parent value. Eventually, in_parent may be deprecated.

Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
 criu/cr-dedup.c        |  2 +-
 criu/include/pagemap.h | 21 +++++++++++++++++++++
 criu/page-xfer.c       | 12 +++++-------
 criu/pagemap.c         | 20 ++++++++++++++------
 criu/uffd.c            |  2 +-
 images/pagemap.proto   |  3 +--
 6 files changed, 43 insertions(+), 17 deletions(-)

diff --git a/criu/cr-dedup.c b/criu/cr-dedup.c
index cc44152..745b17b 100644
--- a/criu/cr-dedup.c
+++ b/criu/cr-dedup.c
@@ -88,7 +88,7 @@ static int cr_dedup_one_pagemap(int id, int flags)
 			goto exit;
 
 		pr_debug("dedup iovec base=%p, len=%zu\n", iov.iov_base, iov.iov_len);
-		if (!pr.pe->in_parent) {
+		if (!pagemap_in_parent(pr.pe)) {
 			ret = dedup_one_iovec(prp, &iov);
 			if (ret)
 				goto exit;
diff --git a/criu/include/pagemap.h b/criu/include/pagemap.h
index f45b2a9..f4a9285 100644
--- a/criu/include/pagemap.h
+++ b/criu/include/pagemap.h
@@ -92,4 +92,25 @@ extern void pagemap2iovec(PagemapEntry *pe, struct iovec *iov);
 extern void iovec2pagemap(struct iovec *iov, PagemapEntry *pe);
 
 extern int dedup_one_iovec(struct page_read *pr, struct iovec *iov);
+
+/* Pagemap flags */
+#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 */
+
+static inline bool pagemap_in_parent(PagemapEntry *pe)
+{
+	return !!(pe->flags & PE_PARENT);
+}
+
+static inline bool pagemap_zero(PagemapEntry *pe)
+{
+	return !!(pe->flags & PE_ZERO);
+}
+
+static inline bool pagemap_lazy(PagemapEntry *pe)
+{
+	return !!(pe->flags & PE_LAZY);
+}
+
 #endif /* __CR_PAGE_READ_H__ */
diff --git a/criu/page-xfer.c b/criu/page-xfer.c
index cd07dee..a02ca3b 100644
--- a/criu/page-xfer.c
+++ b/criu/page-xfer.c
@@ -159,6 +159,7 @@ static int write_pagemap_loc(struct page_xfer *xfer,
 	PagemapEntry pe = PAGEMAP_ENTRY__INIT;
 
 	iovec2pagemap(iov, &pe);
+	pe.has_flags = true;
 	if (opts.auto_dedup && xfer->parent != NULL) {
 		ret = dedup_one_iovec(xfer->parent, iov);
 		if (ret == -1) {
@@ -234,6 +235,7 @@ static int write_hole_loc(struct page_xfer *xfer, struct iovec *iov, int type)
 	PagemapEntry pe = PAGEMAP_ENTRY__INIT;
 
 	iovec2pagemap(iov, &pe);
+	pe.has_flags = true;
 
 	switch (type) {
 	case PS_IOV_HOLE:
@@ -247,17 +249,13 @@ static int write_hole_loc(struct page_xfer *xfer, struct iovec *iov, int type)
 				return -1;
 			}
 		}
-
-		pe.has_in_parent = true;
-		pe.in_parent = true;
+		pe.flags |= PE_PARENT;
 		break;
 	case PS_IOV_ZERO:
-		pe.has_zero = true;
-		pe.zero = true;
+		pe.flags |= PE_ZERO;
 		break;
 	case PS_IOV_LAZY:
-		pe.has_lazy = true;
-		pe.lazy = true;
+		pe.flags |= PE_LAZY;
 		break;
 	default:
 		return -1;
diff --git a/criu/pagemap.c b/criu/pagemap.c
index 47c6788..aaef5a4 100644
--- a/criu/pagemap.c
+++ b/criu/pagemap.c
@@ -95,7 +95,7 @@ int dedup_one_iovec(struct page_read *pr, struct iovec *iov)
 			return -1;
 		pagemap2iovec(pr->pe, &piov);
 		piov_end = (unsigned long)piov.iov_base + piov.iov_len;
-		if (!pr->pe->in_parent) {
+		if (!pagemap_in_parent(pr->pe)) {
 			ret = punch_hole(pr, pr->pi_off, min(piov_end, iov_end) - off, false);
 			if (ret == -1)
 				return ret;
@@ -138,11 +138,11 @@ static int get_pagemap(struct page_read *pr, struct iovec *iov)
 	for (;;) {
 		if (!advance(pr))
 			return 0;
-		if (!pr->pe->zero)
+		if (!pagemap_zero(pr->pe))
 			break;
 	}
 
-	if (pr->pe->in_parent && !pr->parent) {
+	if (pagemap_in_parent(pr->pe) && !pr->parent) {
 		pr_err("No parent for snapshot pagemap\n");
 		return -1;
 	}
@@ -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 (!pr->pe->in_parent && !pr->pe->zero && !pr->pe->lazy)
+	if (!pagemap_in_parent(pr->pe) && !pagemap_zero(pr->pe) && !pagemap_lazy(pr->pe))
 		pr->pi_off += len;
 	pr->cvaddr += len;
 }
@@ -204,7 +204,7 @@ static int read_pagemap_page(struct page_read *pr, unsigned long vaddr, int nr,
 	pr_info("pr%u Read %lx %u pages\n", pr->id, vaddr, nr);
 	pagemap_bound_check(pr->pe, vaddr, nr);
 
-	if (pr->pe->in_parent) {
+	if (pagemap_in_parent(pr->pe)) {
 		struct page_read *ppr = pr->parent;
 
 		/*
@@ -246,7 +246,7 @@ static int read_pagemap_page(struct page_read *pr, unsigned long vaddr, int nr,
 			vaddr += p_nr * PAGE_SIZE;
 			buf += p_nr * PAGE_SIZE;
 		} while (nr);
-	} else if (pr->pe->zero) {
+	} else if (pagemap_zero(pr->pe)) {
 		/* zero mappings should be skipped by get_pagemap */
 		BUG();
 	} else {
@@ -358,6 +358,12 @@ err_cl:
 	return -1;
 }
 
+static void init_compat_pagemap_entry(PagemapEntry *pe)
+{
+	if (pe->has_in_parent && pe->in_parent)
+		pe->flags |= PE_PARENT;
+}
+
 /*
  * The pagemap entry size is at least 8 bytes for small mappings with
  * low address and may get to 18 bytes or even more for large mappings
@@ -393,6 +399,8 @@ static int init_pagemaps(struct page_read *pr)
 		if (ret == 0)
 			break;
 
+		init_compat_pagemap_entry(pr->pmes[pr->nr_pmes]);
+
 		pr->nr_pmes++;
 		if (pr->nr_pmes >= nr_pmes) {
 			nr_pmes += nr_realloc;
diff --git a/criu/uffd.c b/criu/uffd.c
index ebb0e8e..81dc7ae 100644
--- a/criu/uffd.c
+++ b/criu/uffd.c
@@ -372,7 +372,7 @@ static int get_page(struct lazy_pages_info *lpi, unsigned long addr, void *dest)
 	if (ret <= 0)
 		return ret;
 
-	if (lpi->pr.pe->zero)
+	if (pagemap_zero(lpi->pr.pe))
 		return 0;
 
 	ret = lpi->pr.read_pages(&lpi->pr, addr, 1, buf);
diff --git a/images/pagemap.proto b/images/pagemap.proto
index 8b0092f..d5b3433 100644
--- a/images/pagemap.proto
+++ b/images/pagemap.proto
@@ -10,6 +10,5 @@ message pagemap_entry {
 	required uint64 vaddr		= 1 [(criu).hex = true];
 	required uint32 nr_pages	= 2;
 	optional bool	in_parent	= 3;
-	optional bool	zero		= 4;
-	optional bool	lazy		= 5;
+	optional uint32	flags		= 4 [(criu).hex = true];
 }
-- 
1.9.1



More information about the CRIU mailing list