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

Andrei Vagin avagin at virtuozzo.com
Tue Oct 11 09:28:59 PDT 2016


This patch is for criu-dev

On Sat, Oct 08, 2016 at 02:42:07AM +0300, Andrei Vagin wrote:
> 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