[CRIU] [PATCH 2/2] criu: pagemap: split read_pagemap_page into smaller chunks

Mike Rapoport rppt at linux.vnet.ibm.com
Thu Nov 10 00:00:02 PST 2016


Introduce helper functions for reading pages from parent snapshot and for
reading pages from local pages*img

Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
 criu/pagemap.c | 131 +++++++++++++++++++++++++++++++++------------------------
 1 file changed, 75 insertions(+), 56 deletions(-)

diff --git a/criu/pagemap.c b/criu/pagemap.c
index 8dd2e2f..a2f4c85 100644
--- a/criu/pagemap.c
+++ b/criu/pagemap.c
@@ -205,78 +205,97 @@ static inline void pagemap_bound_check(PagemapEntry *pe, unsigned long vaddr, in
 	}
 }
 
-static int read_pagemap_page(struct page_read *pr, unsigned long vaddr, int nr, void *buf)
+static int read_parent_page(struct page_read *pr, unsigned long vaddr,
+			    int nr, void *buf)
 {
+	struct page_read *ppr = pr->parent;
 	int ret;
-	unsigned long len = nr * PAGE_SIZE;
 
-	pr_info("pr%u Read %lx %u pages\n", pr->id, vaddr, nr);
-	pagemap_bound_check(pr->pe, vaddr, nr);
+	/*
+	 * Parent pagemap at this point entry may be shorter
+	 * than the current vaddr:nr needs, so we have to
+	 * carefully 'split' the vaddr:nr into pieces and go
+	 * to parent page-read with the longest requests it
+	 * can handle.
+	 */
 
-	if (pagemap_in_parent(pr->pe)) {
-		struct page_read *ppr = pr->parent;
+	do {
+		int p_nr;
+
+		pr_debug("\tpr%u Read from parent\n", pr->id);
+		ret = seek_pagemap_page(ppr, vaddr, true);
+		if (ret <= 0)
+			return -1;
 
 		/*
-		 * Parent pagemap at this point entry may be shorter
-		 * than the current vaddr:nr needs, so we have to
-		 * carefully 'split' the vaddr:nr into pieces and go
-		 * to parent page-read with the longest requests it
-		 * can handle.
+		 * This is how many pages we have in the parent
+		 * page_read starting from vaddr. Go ahead and
+		 * read as much as we can.
 		 */
+		p_nr = ppr->pe->nr_pages - (vaddr - ppr->pe->vaddr) / PAGE_SIZE;
+		pr_info("\tparent has %u pages in\n", p_nr);
+		if (p_nr > nr)
+			p_nr = nr;
 
-		do {
-			int p_nr;
+		ret = ppr->read_pages(ppr, vaddr, p_nr, buf);
+		if (ret == -1)
+			return ret;
 
-			pr_debug("\tpr%u Read from parent\n", pr->id);
-			ret = seek_pagemap_page(ppr, vaddr, true);
-			if (ret <= 0)
-				return -1;
+		/*
+		 * OK, let's see how much data we have left and go
+		 * to parent page-read again for the next pagemap
+		 * entry.
+		 */
+		nr -= p_nr;
+		vaddr += p_nr * PAGE_SIZE;
+		buf += p_nr * PAGE_SIZE;
+	} while (nr);
 
-			/*
-			 * This is how many pages we have in the parent
-			 * page_read starting from vaddr. Go ahead and
-			 * read as much as we can.
-			 */
-			p_nr = ppr->pe->nr_pages - (vaddr - ppr->pe->vaddr) / PAGE_SIZE;
-			pr_info("\tparent has %u pages in\n", p_nr);
-			if (p_nr > nr)
-				p_nr = nr;
-
-			ret = read_pagemap_page(ppr, vaddr, p_nr, buf);
-			if (ret == -1)
-				return ret;
+	return 0;
+}
 
-			/*
-			 * OK, let's see how much data we have left and go
-			 * to parent page-read again for the next pagemap
-			 * entry.
-			 */
-			nr -= p_nr;
-			vaddr += p_nr * PAGE_SIZE;
-			buf += p_nr * PAGE_SIZE;
-		} while (nr);
-	} else if (pagemap_zero(pr->pe)) {
-		/* zero mappings should be skipped by get_pagemap */
-		BUG();
-	} else {
-		int fd = img_raw_fd(pr->pi);
-		off_t current_vaddr = lseek(fd, pr->pi_off, SEEK_SET);
+static int read_local_page(struct page_read *pr, unsigned long vaddr,
+			   unsigned long len, void *buf)
+{
+	int fd = img_raw_fd(pr->pi);
+	off_t current_vaddr = lseek(fd, pr->pi_off, SEEK_SET);
+	int ret;
 
-		pr_debug("\tpr%u Read page from self %lx/%"PRIx64"\n", pr->id, pr->cvaddr, current_vaddr);
-		ret = read(fd, buf, len);
-		if (ret != len) {
-			pr_perror("Can't read mapping page %d", ret);
+	pr_debug("\tpr%u Read page from self %lx/%"PRIx64"\n", pr->id, pr->cvaddr, current_vaddr);
+	ret = read(fd, buf, len);
+	if (ret != len) {
+		pr_perror("Can't read mapping page %d", ret);
+		return -1;
+	}
+
+	pr->pi_off += len;
+
+	if (opts.auto_dedup) {
+		ret = punch_hole(pr, current_vaddr, len, false);
+		if (ret == -1) {
 			return -1;
 		}
+	}
 
-		pr->pi_off += len;
+	return 0;
+}
 
-		if (opts.auto_dedup) {
-			ret = punch_hole(pr, current_vaddr, len, false);
-			if (ret == -1) {
-				return -1;
-			}
-		}
+static int read_pagemap_page(struct page_read *pr, unsigned long vaddr, int nr, void *buf)
+{
+	unsigned long len = nr * PAGE_SIZE;
+
+	pr_info("pr%u Read %lx %u pages\n", pr->id, vaddr, nr);
+	pagemap_bound_check(pr->pe, vaddr, nr);
+
+	if (pagemap_in_parent(pr->pe)) {
+		if (read_parent_page(pr, vaddr, nr, buf) < 0)
+			return -1;
+	} else if (pagemap_zero(pr->pe)) {
+		/* zero mappings should be skipped by get_pagemap */
+		BUG();
+	} else {
+		if (read_local_page(pr, vaddr, len, buf) < 0)
+			return -1;
 	}
 
 	pr->cvaddr += len;
-- 
1.9.1



More information about the CRIU mailing list