[CRIU] [PATCH 4/7] pagemap: replace seek_page with seek_pagemap method

Mike Rapoport rppt at linux.vnet.ibm.com
Sun Nov 20 01:50:03 PST 2016


The only external users of ->seek_page method are page-xfer and uffd and
both of them are anyway interested in the entire pagemap rather than a
particular page.
The added 'skip_zero' parameter allows proper detection of zero pagemaps by
uffd.

Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
 criu/include/pagemap.h |  3 ++-
 criu/page-xfer.c       |  2 +-
 criu/pagemap.c         | 23 ++++++++++++++++++-----
 criu/uffd.c            | 11 +++++------
 4 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/criu/include/pagemap.h b/criu/include/pagemap.h
index 54c147a..ea106ec 100644
--- a/criu/include/pagemap.h
+++ b/criu/include/pagemap.h
@@ -54,7 +54,8 @@ struct page_read {
 	int (*advance)(struct page_read *pr);
 	void (*close)(struct page_read *);
 	void (*skip_pages)(struct page_read *, unsigned long len);
-	int (*seek_page)(struct page_read *pr, unsigned long vaddr);
+	int (*seek_pagemap)(struct page_read *pr, unsigned long vaddr,
+			    bool skip_zero);
 	void (*reset)(struct page_read *pr);
 	int (*sync)(struct page_read *pr);
 
diff --git a/criu/page-xfer.c b/criu/page-xfer.c
index f308972..79008ad 100644
--- a/criu/page-xfer.c
+++ b/criu/page-xfer.c
@@ -208,7 +208,7 @@ static int check_pagehole_in_parent(struct page_read *p, struct iovec *iov)
 		struct iovec piov;
 		unsigned long pend;
 
-		ret = p->seek_page(p, off);
+		ret = p->seek_pagemap(p, off, true);
 		if (ret <= 0 || !p->pe) {
 			pr_err("Missing %lx in parent pagemap\n", off);
 			return -1;
diff --git a/criu/pagemap.c b/criu/pagemap.c
index 3c2fc5c..2521e57 100644
--- a/criu/pagemap.c
+++ b/criu/pagemap.c
@@ -83,6 +83,8 @@ static int punch_hole(struct page_read *pr, unsigned long off,
 	return 0;
 }
 
+static int seek_pagemap_page(struct page_read *pr, unsigned long vaddr);
+
 int dedup_one_iovec(struct page_read *pr, struct iovec *iov)
 {
 	unsigned long off;
@@ -97,7 +99,7 @@ int dedup_one_iovec(struct page_read *pr, struct iovec *iov)
 		struct iovec tiov;
 		struct page_read * prp;
 
-		ret = pr->seek_page(pr, off);
+		ret = seek_pagemap_page(pr, off);
 		if (ret == 0) {
 			pr_err("Missing %lx in parent pagemap\n", off);
 			if (off < pr->cvaddr && pr->cvaddr < iov_end)
@@ -177,7 +179,8 @@ static void skip_pagemap_pages(struct page_read *pr, unsigned long len)
 	pr->cvaddr += len;
 }
 
-static int seek_pagemap_page(struct page_read *pr, unsigned long vaddr)
+static int seek_pagemap(struct page_read *pr, unsigned long vaddr,
+			bool skip_zero)
 {
 	if (!pr->pe)
 		advance(pr);
@@ -187,14 +190,14 @@ static int seek_pagemap_page(struct page_read *pr, unsigned long vaddr)
 		unsigned long len = pr->pe->nr_pages * PAGE_SIZE;
 		unsigned long end = start + len;
 
-		if (pagemap_zero(pr->pe))
+		if (skip_zero && pagemap_zero(pr->pe))
 			continue;
 
 		if (vaddr < pr->cvaddr)
 			break;
 
 		if (vaddr >= start && vaddr < end) {
-			skip_pagemap_pages(pr, vaddr - pr->cvaddr);
+			skip_pagemap_pages(pr, start - pr->cvaddr);
 			return 1;
 		}
 
@@ -205,6 +208,16 @@ static int seek_pagemap_page(struct page_read *pr, unsigned long vaddr)
 	return 0;
 }
 
+static int seek_pagemap_page(struct page_read *pr, unsigned long vaddr)
+{
+	if (seek_pagemap(pr, vaddr, true)) {
+		skip_pagemap_pages(pr, vaddr - pr->cvaddr);
+		return 1;
+	}
+
+	return 0;
+}
+
 static inline void pagemap_bound_check(PagemapEntry *pe, unsigned long vaddr, int nr)
 {
 	if (vaddr < pe->vaddr || (vaddr - pe->vaddr) / PAGE_SIZE + nr > pe->nr_pages) {
@@ -720,7 +733,7 @@ int open_page_read_at(int dfd, int pid, struct page_read *pr, int pr_flags)
 	pr->advance = advance;
 	pr->close = close_page_read;
 	pr->skip_pages = skip_pagemap_pages;
-	pr->seek_page = seek_pagemap_page;
+	pr->seek_pagemap = seek_pagemap;
 	pr->reset = reset_pagemap;
 	pr->sync = process_async_reads;
 	pr->io_complete = NULL; /* set up by the client if needed */
diff --git a/criu/uffd.c b/criu/uffd.c
index 71fed07..3e3f320 100644
--- a/criu/uffd.c
+++ b/criu/uffd.c
@@ -618,12 +618,11 @@ static int uffd_seek_or_zero_pages(struct lazy_pages_info *lpi, __u64 address,
 
 	lpi->pr.reset(&lpi->pr);
 
-	/*
-	 * FIXME: rework zeroes handling so we won't need to rely on
-	 * seek_page return value here
-	 */
-	ret = lpi->pr.seek_page(&lpi->pr, address);
-	if (ret == 0 || pagemap_zero(lpi->pr.pe))
+	ret = lpi->pr.seek_pagemap(&lpi->pr, address, false);
+	if (!ret)
+		return 0;
+
+	if (pagemap_zero(lpi->pr.pe))
 		return uffd_zero(lpi, address, nr);
 
 	return 1;
-- 
1.9.1



More information about the CRIU mailing list