[CRIU] [PATCH v4 4/7] shmem: dump anon shared memory pages according to their PME derived states

Eugene Batalov eabatalov89 at gmail.com
Thu Aug 11 07:53:54 PDT 2016


From: Fyodor Bocharov <bocharovfedor at gmail.com>

This allows us not to dump anon shmem pages that weren't changed since
last dump. We dump each anon shmem vma using page-xfer. page-xfer does all
magic with storing "in_parent" field in pagemap-entry.
When restoring we simply read every page with page-read and it does
all magic of reading from right place in image hierarchy.
auto-dedup on restore is already implemented by page-read so we don't need
to code it.

Signed-off-by: Fyodor Bocharov <fbocharov at yandex.ru>
Signed-off-by: Eugene Batalov <eabatalov89 at gmail.com>
---
 criu/shmem.c | 35 +++++++++++++++--------------------
 1 file changed, 15 insertions(+), 20 deletions(-)

diff --git a/criu/shmem.c b/criu/shmem.c
index ad6d7d6..a21e8c1 100644
--- a/criu/shmem.c
+++ b/criu/shmem.c
@@ -607,17 +607,11 @@ static int dump_one_shmem(struct shmem_info *si)
 	struct page_pipe *pp;
 	struct page_xfer xfer;
 	int err, ret = -1, fd;
-	unsigned char *map = NULL;
 	void *addr = NULL;
 	unsigned long pfn, nrpages;
 
 	pr_info("Dumping shared memory %ld\n", si->shmid);
 
-	nrpages = (si->size + PAGE_SIZE - 1) / PAGE_SIZE;
-	map = xmalloc(nrpages * sizeof(*map));
-	if (!map)
-		goto err;
-
 	fd = open_proc(si->pid, "map_files/%lx-%lx", si->start, si->end);
 	if (fd < 0)
 		goto err;
@@ -630,17 +624,7 @@ static int dump_one_shmem(struct shmem_info *si)
 		goto err;
 	}
 
-	/*
-	 * We can't use pagemap here, because this vma is
-	 * not mapped to us at all, but mincore reports the
-	 * pagecache status of a file, which is correct in
-	 * this case.
-	 */
-
-	err = mincore(addr, si->size, map);
-	if (err)
-		goto err_unmap;
-
+	nrpages = (si->size + PAGE_SIZE - 1) / PAGE_SIZE;
 	pp = create_page_pipe((nrpages + 1) / 2, NULL, PP_CHUNK_MODE);
 	if (!pp)
 		goto err_unmap;
@@ -650,10 +634,22 @@ static int dump_one_shmem(struct shmem_info *si)
 		goto err_pp;
 
 	for (pfn = 0; pfn < nrpages; pfn++) {
-		if (!(map[pfn] & PAGE_RSS))
+		unsigned int pgstate;
+		unsigned long pgaddr;
+
+		pgstate = get_pstate(si->pstate_map, pfn);
+		if (pgstate == PST_DONT_DUMP)
 			continue;
+
+		pgaddr = (unsigned long)addr + pfn * PAGE_SIZE;
 again:
-		ret = page_pipe_add_page(pp, (unsigned long)addr + pfn * PAGE_SIZE, 0);
+		if (pgstate == PST_ZERO)
+			ret = page_pipe_add_hole(pp, pgaddr, PP_HOLE_ZERO);
+		else if (xfer.parent && page_in_parent(pgstate == PST_DIRTY))
+			ret = page_pipe_add_hole(pp, pgaddr, PP_HOLE_PARENT);
+		else /* pgstate == PST_DUMP */
+			ret = page_pipe_add_page(pp, pgaddr, 0);
+
 		if (ret == -EAGAIN) {
 			ret = dump_pages(pp, &xfer, addr);
 			if (ret)
@@ -673,7 +669,6 @@ err_pp:
 err_unmap:
 	munmap(addr,  si->size);
 err:
-	xfree(map);
 	return ret;
 }
 
-- 
1.9.1



More information about the CRIU mailing list