[CRIU] [PATCH RFC 2/2] criu: page-read: read pagemaps at open time and keep them in memory

Andrew Vagin avagin at virtuozzo.com
Fri Jun 24 16:02:20 PDT 2016


> +                                           nr_pmes *
> sizeof(*pr->pmes));
> +                       if (!pr->pmes)
> +                               goto free_pagemaps;
> +               }
> +       }
> +
> +       return 0;

CID 163578 (#1 of 1): Structurally dead code (UNREACHABLE)
unreachable: This code cannot be reached: close_image(pr->pmi)

> +
> +       close_image(pr->pmi);
> +       pr->pmi = NULL;
> +
> +free_pagemaps:
> +       free_pagemaps(pr);
> +       return -1;
> +}


On Thu, Jun 02, 2016 at 04:10:06PM +0300, Mike Rapoport wrote:
> Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
> ---
>  criu/include/page-read.h |  4 +++
>  criu/page-read.c         | 78 ++++++++++++++++++++++++++++++++++++++++++++----
>  2 files changed, 77 insertions(+), 5 deletions(-)
> 
> diff --git a/criu/include/page-read.h b/criu/include/page-read.h
> index 4b6b5b7..4c6d21e 100644
> --- a/criu/include/page-read.h
> +++ b/criu/include/page-read.h
> @@ -68,6 +68,10 @@ struct page_read {
>  	struct iovec bunch;		/* record consequent neighbour
>  					   iovecs to punch together */
>  	unsigned id; /* for logging */
> +
> +	PagemapEntry **pmes;
> +	int nr_pmes;
> +	int curr_pme;
>  };
>  
>  #define PR_SHMEM	0x1
> diff --git a/criu/page-read.c b/criu/page-read.c
> index 933f047..51c913d 100644
> --- a/criu/page-read.c
> +++ b/criu/page-read.c
> @@ -59,12 +59,12 @@ void iovec2pagemap(struct iovec *iov, PagemapEntry *pe)
>  
>  static int get_pagemap(struct page_read *pr, struct iovec *iov)
>  {
> -	int ret;
>  	PagemapEntry *pe;
>  
> -	ret = pb_read_one_eof(pr->pmi, &pe, PB_PAGEMAP);
> -	if (ret <= 0)
> -		return ret;
> +	if (pr->curr_pme >= pr->nr_pmes)
> +		return 0;
> +
> +	pe = pr->pmes[pr->curr_pme];
>  
>  	pagemap2iovec(pe, iov);
>  
> @@ -81,7 +81,7 @@ static int get_pagemap(struct page_read *pr, struct iovec *iov)
>  
>  static void put_pagemap(struct page_read *pr)
>  {
> -	pagemap_entry__free_unpacked(pr->pe, NULL);
> +	pr->curr_pme++;
>  }
>  
>  static void skip_pagemap_pages(struct page_read *pr, unsigned long len)
> @@ -216,6 +216,16 @@ static int read_pagemap_page(struct page_read *pr, unsigned long vaddr, int nr,
>  	return 1;
>  }
>  
> +static void free_pagemaps(struct page_read *pr)
> +{
> +	int i;
> +
> +	for (i = 0; i < pr->nr_pmes; i++)
> +		pagemap_entry__free_unpacked(pr->pmes[i], NULL);
> +
> +	xfree(pr->pmes);
> +}
> +
>  static void close_page_read(struct page_read *pr)
>  {
>  	int ret;
> @@ -236,6 +246,9 @@ static void close_page_read(struct page_read *pr)
>  	close_image(pr->pmi);
>  	if (pr->pi)
>  		close_image(pr->pi);
> +
> +	if (pr->pmes)
> +		free_pagemaps(pr);
>  }
>  
>  static int try_open_parent(int dfd, int pid, struct page_read *pr, int pr_flags)
> @@ -272,6 +285,56 @@ err_cl:
>  	return -1;
>  }
>  
> +/*
> + * The pagemap entry size is at least 8 bytes for small mappings with
> + * low address and may get to 18 bytes or even more for large mappings
> + * with high address and in_parent flag set. 16 seems to be nice round
> + * number to minimize {over,under}-allocations
> + */
> +#define PAGEMAP_ENTRY_SIZE_ESTIMATE 16
> +
> +static int init_pagemaps(struct page_read *pr)
> +{
> +	off_t fsize;
> +	int nr_pmes, nr_realloc;
> +
> +	fsize = img_raw_size(pr->pmi);
> +	if (fsize < 0)
> +		return -1;
> +
> +	nr_pmes = fsize / PAGEMAP_ENTRY_SIZE_ESTIMATE + 1;
> +	nr_realloc = nr_pmes / 2;
> +
> +	pr->pmes = xzalloc(nr_pmes * sizeof(*pr->pmes));
> +	if (!pr->pmes)
> +		return -1;
> +
> +	pr->nr_pmes = pr->curr_pme = 0;
> +
> +	while (1) {
> +		int ret = pb_read_one_eof(pr->pmi, &pr->pmes[pr->nr_pmes],
> +					  PB_PAGEMAP);
> +		if (ret < 0)
> +			goto free_pagemaps;
> +		if (ret == 0)
> +			break;
> +
> +		if (pr->nr_pmes++ >= nr_pmes) {
> +			nr_pmes += nr_realloc;
> +			pr->pmes = xrealloc(pr->pmes,
> +					    nr_pmes * sizeof(*pr->pmes));
> +			if (!pr->pmes)
> +				goto free_pagemaps;
> +		}
> +	}
> +
> +	return 0;
> +
> +free_pagemaps:
> +	free_pagemaps(pr);
> +	return -1;
> +}
> +
>  int open_page_read_at(int dfd, int pid, struct page_read *pr, int pr_flags)
>  {
>  	int flags, i_typ, i_typ_o;
> @@ -323,6 +386,11 @@ int open_page_read_at(int dfd, int pid, struct page_read *pr, int pr_flags)
>  		return -1;
>  	}
>  
> +	if (init_pagemaps(pr)) {
> +		close_page_read(pr);
> +		return -1;
> +	}
> +
>  	pr->get_pagemap = get_pagemap;
>  	pr->put_pagemap = put_pagemap;
>  	pr->read_pages = read_pagemap_page;
> -- 
> 1.9.1
> 
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu


More information about the CRIU mailing list