[CRIU] [PATCH v3 09/12] shmem: implement anon shared memory dedup on dump
Pavel Emelyanov
xemul at virtuozzo.com
Wed Aug 10 06:22:17 PDT 2016
Dedup?! From this patch it seems to me that we just change RSS bit
from mincore() into PME_PRESENT bits from pagemaps.
On 08/07/2016 04:11 PM, Eugene Batalov wrote:
> From: Fyodor Bocharov <bocharovfedor at gmail.com>
>
> Dedup works as following: when dumping anon shmem vma we are checking its
> every page for dirtiness (this info stored in bitmap with each anon shmem
> vma). We dump each anon shmem vma using page-xfer. page-xfer does all
> magic with storing "in_parent" field in pagemap-entry.
> When restoring from deduplicated image 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 | 42 +++++++++++++++++++++---------------------
> 1 file changed, 21 insertions(+), 21 deletions(-)
>
> diff --git a/criu/shmem.c b/criu/shmem.c
> index f59a2e6..a91e085 100644
> --- a/criu/shmem.c
> +++ b/criu/shmem.c
> @@ -2,6 +2,7 @@
> #include <sys/mman.h>
> #include <stdlib.h>
> #include <fcntl.h>
> +#include <stdbool.h>
>
> #include "list.h"
> #include "pid.h"
> @@ -430,7 +431,9 @@ static int restore_shmem_content(void *addr, struct shmem_info *si)
> if (vaddr + nr_pages * PAGE_SIZE > si->size)
> break;
>
> - pr.read_pages(&pr, vaddr, nr_pages, addr + vaddr);
> + ret = pr.read_pages(&pr, vaddr, nr_pages, addr + vaddr);
> + if (ret < 0)
> + break;
>
> if (pr.put_pagemap)
> pr.put_pagemap(&pr);
> @@ -586,17 +589,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;
> @@ -609,17 +606,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;
> @@ -629,10 +616,24 @@ static int dump_one_shmem(struct shmem_info *si)
> goto err_pp;
>
> for (pfn = 0; pfn < nrpages; pfn++) {
> - if (!(map[pfn] & PAGE_RSS))
> + bool used;
> + bool dirty;
> + unsigned long pgaddr;
> +
> + used = test_bit(pfn, si->pused_map);
> + if (!used)
> continue;
> +
> + dirty = test_bit(pfn, si->pdirty_map);
> + pgaddr = (unsigned long)addr + pfn * PAGE_SIZE;
> again:
> - ret = page_pipe_add_page(pp, (unsigned long)addr + pfn * PAGE_SIZE, 0);
> + if (page_is_zero(pfn))
> + ret = page_pipe_add_hole(pp, pgaddr, PP_HOLE_ZERO);
> + else if (xfer.parent && page_in_parent(dirty))
> + ret = page_pipe_add_hole(pp, pgaddr, PP_HOLE_PARENT);
> + else
> + ret = page_pipe_add_page(pp, pgaddr, 0);
> +
> if (ret == -EAGAIN) {
> ret = dump_pages(pp, &xfer, addr);
> if (ret)
> @@ -652,7 +653,6 @@ err_pp:
> err_unmap:
> munmap(addr, si->size);
> err:
> - xfree(map);
> return ret;
> }
>
>
More information about the CRIU
mailing list