[CRIU] [PATCHv0 7/8] shmem: implement anon shared memory autodedup

Pavel Emelyanov xemul at parallels.com
Tue Dec 8 04:59:50 PST 2015


> @@ -386,23 +374,29 @@ static int dump_pages(struct page_pipe *pp, struct page_xfer *xfer, void *addr)
>  	return page_xfer_dump_pages(xfer, pp, (unsigned long)addr);
>  }
>  
> +/* Implementation comes from mem.c */
> +
> +static inline bool page_in_parent(unsigned long dirty)
> +{
> +	/*
> +	 * If we do memory tracking, but w/o parent images,
> +	 * then we have to dump all memory
> +	 */
> +
> +	return opts.track_mem && opts.img_parent && !dirty;
> +}

Don't copy code, better put this into include/mem.h

> +
>  static int dump_one_shmem(struct shmem_info_dump *si)
>  {
>  	struct iovec *iovs;
>  	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;
> @@ -415,17 +409,7 @@ static int dump_one_shmem(struct shmem_info_dump *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 = BLOCKS_CNT(si->size, PAGE_SIZE);
>  	iovs = xmalloc(((nrpages + 1) / 2) * sizeof(struct iovec));
>  	if (!iovs)
>  		goto err_unmap;
> @@ -439,10 +423,13 @@ static int dump_one_shmem(struct shmem_info_dump *si)
>  		goto err_pp;
>  
>  	for (pfn = 0; pfn < nrpages; pfn++) {
> -		if (!(map[pfn] & PAGE_RSS))
> -			continue;
> +		unsigned long dirty = test_bit(pfn, si->pdirty_map);
>  again:
> -		ret = page_pipe_add_page(pp, (unsigned long)addr + pfn * PAGE_SIZE);
> +		if (xfer.parent && page_in_parent(dirty))
> +			ret = page_pipe_add_hole(pp, (unsigned long)addr + pfn * PAGE_SIZE);
> +		else
> +			ret = page_pipe_add_page(pp, (unsigned long)addr + pfn * PAGE_SIZE);
> +
>  		if (ret == -EAGAIN) {
>  			ret = dump_pages(pp, &xfer, addr);
>  			if (ret)
> @@ -464,7 +451,6 @@ err_iovs:
>  err_unmap:
>  	munmap(addr,  si->size);
>  err:
> -	xfree(map);
>  	return ret;
>  }
>  
> 



More information about the CRIU mailing list