[CRIU] [PATCH] pcs7: shmem -- Inspect pages before the dump

Andrei Vagin avagin at openvz.org
Fri Oct 7 16:42:07 PDT 2016


From: Cyrill Gorcunov <gorcunov at virtuozzo.com>

When pages are swapped out we can't detect their presence
with mincore. Instead lest do a trick: walk over pagerange
and touch pages so we can use @pagemap then and inspect
the pages status.

https://jira.sw.ru/browse/PSBM-52138

Suggested-by: Andrei Vagin <avagin at openvz.org>
Signed-off-by: Cyrill Gorcunov <gorcunov at virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin at virtuozzo.com>
---
 criu/include/image.h |  2 --
 criu/shmem.c         | 33 +++++++++++++++++++++++++++------
 2 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/criu/include/image.h b/criu/include/image.h
index 65b7b0a..af59ea2 100644
--- a/criu/include/image.h
+++ b/criu/include/image.h
@@ -16,8 +16,6 @@
 #else
 #define PAGE_IMAGE_SIZE	4096
 #endif /* _ARCH_PPC64 */
-#define PAGE_RSS	1
-#define PAGE_ANON	2
 
 /*
  * Top bit set in the tgt id means we've remapped
diff --git a/criu/shmem.c b/criu/shmem.c
index ebd22ec..023428b 100644
--- a/criu/shmem.c
+++ b/criu/shmem.c
@@ -631,8 +631,8 @@ static int dump_one_shmem(struct shmem_info *si)
 {
 	struct page_pipe *pp;
 	struct page_xfer xfer;
-	int err, ret = -1, fd;
-	unsigned char *mc_map = NULL;
+	int err, ret = -1, fd, fd_map;
+	u64 *mc_map = NULL;
 	void *addr = NULL;
 	unsigned long pfn, nrpages;
 
@@ -651,13 +651,32 @@ static int dump_one_shmem(struct shmem_info *si)
 	}
 
 	nrpages = (si->size + PAGE_SIZE - 1) / PAGE_SIZE;
+
+	/*
+	 * Make sure PTEs are created in our space
+	 * so pagemap would show us the proper results.
+	 */
+	for (pfn = 0; pfn < nrpages; pfn++) {
+		volatile char v = *(char *)((unsigned long)addr + pfn * PAGE_SIZE);
+		(void)v;
+	}
+
 	mc_map = xmalloc(nrpages * sizeof(*mc_map));
 	if (!mc_map)
 		goto err_unmap;
-	/* We can't rely only on PME bits for anon shmem */
-	err = mincore(addr, si->size, mc_map);
-	if (err)
+
+	fd_map = open_proc(PROC_SELF, "pagemap");
+	if (fd_map < 0) {
 		goto err_unmap;
+	}
+	if (pread(fd_map, mc_map, nrpages * sizeof(*mc_map),
+		  PAGE_PFN((unsigned long)addr) * sizeof(u64)) != nrpages * sizeof(*mc_map)) {
+		pr_perror("Can't read shmem 0x%lx (0x%lx-0x%lx) pagemap\n",
+			  si->shmid, si->start, si->end);
+		close(fd_map);
+		goto err_unmap;
+	}
+	close(fd_map);
 
 	pp = create_page_pipe((nrpages + 1) / 2, NULL, PP_CHUNK_MODE);
 	if (!pp)
@@ -677,7 +696,9 @@ static int dump_one_shmem(struct shmem_info *si)
 			use_mc = pgstate == PST_DONT_DUMP;
 		}
 
-		if (use_mc && !(mc_map[pfn] & PAGE_RSS))
+		if (use_mc &&
+		   (!(mc_map[pfn] & (PME_PRESENT | PME_SWAP)) ||
+		    page_is_zero(mc_map[pfn])))
 			continue;
 
 		pgaddr = (unsigned long)addr + pfn * PAGE_SIZE;
-- 
2.7.4



More information about the CRIU mailing list