[CRIU] [PATCH] criu: pagemap: don't traverse the entire pagemap while seeking a page

Mike Rapoport rppt at linux.vnet.ibm.com
Thu Sep 15 06:40:16 PDT 2016


Since commit 95009c4c6d5 (criu: pagemap: introduce advance() helper for
pagemap iteration) seek_pagemap_page traverses the entire pagemap, rather
than starts each time from the last pagemap that was used.
With large pagemaps (like, e.g. in maps05 case) the new behavior causes
exponential increase in amount of calls to skip_pagemap_page for every new
snapshot.
Let's restore the original behavior.

Fixes: #217

Reported-by: Andrey Vagin <avagin at openvz.org>
Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
 criu/pagemap.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/criu/pagemap.c b/criu/pagemap.c
index aaef5a4..2b8560d 100644
--- a/criu/pagemap.c
+++ b/criu/pagemap.c
@@ -166,9 +166,10 @@ static void skip_pagemap_pages(struct page_read *pr, unsigned long len)
 static int seek_pagemap_page(struct page_read *pr, unsigned long vaddr,
 			     bool warn)
 {
-	pr->reset(pr);
+	if (!pr->pe)
+		advance(pr);
 
-	while (advance(pr)) {
+	do {
 		unsigned long start = pr->pe->vaddr;
 		unsigned long len = pr->pe->nr_pages * PAGE_SIZE;
 		unsigned long end = start + len;
@@ -180,7 +181,7 @@ static int seek_pagemap_page(struct page_read *pr, unsigned long vaddr,
 
 		if (end <= vaddr)
 			skip_pagemap_pages(pr, end - pr->cvaddr);
-	}
+	} while (advance(pr));
 
 	if (warn)
 		pr_err("Missing %lx in parent pagemap\n", vaddr);
-- 
1.9.1



More information about the CRIU mailing list