[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