[CRIU] [RFC PATCH 1/7] lazy-pages: extend the page_read with ability to read remote pages

Pavel Emelyanov xemul at virtuozzo.com
Tue Nov 15 07:40:06 PST 2016


On 11/14/2016 06:37 PM, Mike Rapoport wrote:
> Currently lazy-pages daemon uses either pr->read_pages or get_remote_pages
> to get actual page data from local images or remote server. From now on,
> page_read will be completely responsible for getting the page data.
> 
> Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
> ---
>  criu/include/pagemap.h |  7 ++++++-
>  criu/pagemap.c         | 32 +++++++++++++++++++++++++++-----
>  criu/uffd.c            | 11 +++++------
>  3 files changed, 38 insertions(+), 12 deletions(-)
> 
> diff --git a/criu/include/pagemap.h b/criu/include/pagemap.h
> index 711e169..e4a4ecd 100644
> --- a/criu/include/pagemap.h
> +++ b/criu/include/pagemap.h
> @@ -58,6 +58,9 @@ struct page_read {
>  	void (*reset)(struct page_read *pr);
>  	int (*sync)(struct page_read *pr);
>  
> +	int (*maybe_read_page)(struct page_read *pr, unsigned long vaddr,
> +			       unsigned long len, void *buf, unsigned flags);
> +
>  	/* Private data of reader */
>  	struct cr_img *pmi;
>  	struct cr_img *pi;
> @@ -72,7 +75,8 @@ struct page_read {
>  
>  	struct iovec bunch;		/* record consequent neighbour
>  					   iovecs to punch together */
> -	unsigned id; /* for logging */
> +	unsigned id;			/* for logging */
> +	int pid;			/* PID of the process */
>  
>  	PagemapEntry **pmes;
>  	int nr_pmes;
> @@ -90,6 +94,7 @@ struct page_read {
>  
>  #define PR_TYPE_MASK	0x3
>  #define PR_MOD		0x4	/* Will need to modify */
> +#define PR_REMOTE	0x8
>  
>  /*
>   * -1 -- error
> diff --git a/criu/pagemap.c b/criu/pagemap.c
> index 1112515..728b031 100644
> --- a/criu/pagemap.c
> +++ b/criu/pagemap.c
> @@ -10,6 +10,7 @@
>  #include "cr_options.h"
>  #include "servicefd.h"
>  #include "pagemap.h"
> +#include "page-xfer.h"
>  
>  #include "xmalloc.h"
>  #include "protobuf.h"
> @@ -377,8 +378,8 @@ static int enqueue_async_page(struct page_read *pr, unsigned long vaddr,
>  	return 0;
>  }
>  
> -static int maybe_read_page(struct page_read *pr, unsigned long vaddr,
> -			   unsigned long len, void *buf, unsigned flags)
> +static int maybe_read_page_local(struct page_read *pr, unsigned long vaddr,
> +				 unsigned long len, void *buf, unsigned flags)
>  {
>  	int ret;
>  
> @@ -392,6 +393,19 @@ static int maybe_read_page(struct page_read *pr, unsigned long vaddr,
>  	return ret;
>  }
>  
> +static int maybe_read_page_remote(struct page_read *pr, unsigned long vaddr,
> +				  unsigned long len, void *buf, unsigned flags)
> +{
> +	int ret;
> +
> +	if (flags & PR_ASYNC)
> +		ret = -1;	/* not yet supported */
> +	else
> +		ret = get_remote_pages(pr->pid, vaddr, len / PAGE_SIZE, buf);
> +
> +	return ret;
> +}
> +
>  static int read_pagemap_page(struct page_read *pr, unsigned long vaddr, int nr,
>  			     void *buf, unsigned flags)
>  {
> @@ -407,7 +421,7 @@ static int read_pagemap_page(struct page_read *pr, unsigned long vaddr, int nr,
>  		/* zero mappings should be skipped by get_pagemap */
>  		BUG();
>  	} else {
> -		if (maybe_read_page(pr, vaddr, len, buf, flags) < 0)
> +		if (pr->maybe_read_page(pr, vaddr, len, buf, flags) < 0)
>  			return -1;
>  	}
>  
> @@ -605,6 +619,7 @@ int open_page_read_at(int dfd, int pid, struct page_read *pr, int pr_flags)
>  {
>  	int flags, i_typ;
>  	static unsigned ids = 1;
> +	bool remote = pr_flags & PR_REMOTE;
>  
>  	if (opts.auto_dedup)
>  		pr_flags |= PR_MOD;
> @@ -668,9 +683,16 @@ int open_page_read_at(int dfd, int pid, struct page_read *pr, int pr_flags)

Here between these lines we have call to try_open_parent(), but parent
page_read-s are always local, so the PR_REMOTE flag should (probably)
be dropped. Should it?

>  	pr->reset = reset_pagemap;
>  	pr->sync = process_async_reads;
>  	pr->id = ids++;
> +	pr->pid = pid;
> +
> +	if (remote)
> +		pr->maybe_read_page = maybe_read_page_remote;
> +	else
> +		pr->maybe_read_page = maybe_read_page_local;
>  
> -	pr_debug("Opened page read %u (parent %u)\n",
> -			pr->id, pr->parent ? pr->parent->id : 0);
> +	pr_debug("Opened %s page read %u (parent %u)\n",
> +		 remote ? "remote" : "local", pr->id,
> +		 pr->parent ? pr->parent->id : 0);
>  
>  	return 1;
>  }
> diff --git a/criu/uffd.c b/criu/uffd.c
> index 06857fd..3eddf85 100644
> --- a/criu/uffd.c
> +++ b/criu/uffd.c
> @@ -452,6 +452,7 @@ static int ud_open(int client, struct lazy_pages_info **_lpi)
>  	struct lazy_pages_info *lpi;
>  	int ret = -1;
>  	int uffd_flags;
> +	int pr_flags = PR_TASK;
>  
>  	lpi = lpi_init();
>  	if (!lpi)
> @@ -485,7 +486,9 @@ static int ud_open(int client, struct lazy_pages_info **_lpi)
>  	uffd_flags = fcntl(lpi->lpfd.fd, F_GETFD, NULL);
>  	pr_debug("uffd_flags are 0x%x\n", uffd_flags);
>  
> -	ret = open_page_read(lpi->pid, &lpi->pr, PR_TASK);
> +	if (opts.use_page_server)
> +		pr_flags |= PR_REMOTE;
> +	ret = open_page_read(lpi->pid, &lpi->pr, pr_flags);
>  	if (ret <= 0) {
>  		ret = -1;
>  		goto out;
> @@ -584,11 +587,7 @@ static int uffd_handle_pages(struct lazy_pages_info *lpi, __u64 address, int nr)
>  	if (ret == 0 || pagemap_zero(lpi->pr.pe))
>  		return uffd_zero(lpi, address, nr);
>  
> -	if (opts.use_page_server)
> -		ret = get_remote_pages(lpi->pid, address, nr, lpi->buf);
> -	else
> -		ret = lpi->pr.read_pages(&lpi->pr, address, nr, lpi->buf, 0);
> -
> +	ret = lpi->pr.read_pages(&lpi->pr, address, nr, lpi->buf, 0);
>  	if (ret <= 0) {
>  		pr_err("%d: failed reading pages at %llx\n", lpi->pid, address);
>  		return ret;
> 



More information about the CRIU mailing list