criu: pagemap: don't traverse the entire pagemap while seeking a page

Submitted by Mike Rapoport on Sept. 15, 2016, 1:40 p.m.

Details

Message ID 1473946816-13449-1-git-send-email-rppt@linux.vnet.ibm.com
State Rejected
Series "criu: pagemap: don't traverse the entire pagemap while seeking a page"
Headers show

Commit Message

Mike Rapoport Sept. 15, 2016, 1:40 p.m.
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@openvz.org>
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
---
 criu/pagemap.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

Patch hide | download patch | download mbox

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);