[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