[CRIU] [PATCH] page-pipe: do not allow pipe sharing between different PPB types

Andrei Vagin avagin at virtuozzo.com
Fri Feb 16 03:25:21 MSK 2018


Applied, thanks

On Sun, Feb 11, 2018 at 03:53:15PM +0200, Mike Rapoport wrote:
> Currently, if pipe is shared between lazy and non-lazy PPBs lazy migration
> fails because data that should be transfered on demand is spliced into the
> images. Preventing pipe sharing between PPBs of different type resolves
> this issue.
> In order to still minimize pipe fragmentation, we track the last pipe that
> was used for certain PPB type and re-use it for the PPB of the same type.
> 
> Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
> ---
>  criu/include/page-pipe.h | 11 +++++++++++
>  criu/page-pipe.c         | 43 +++++++++++++++++++++++++++++++++++++------
>  2 files changed, 48 insertions(+), 6 deletions(-)
> 
> diff --git a/criu/include/page-pipe.h b/criu/include/page-pipe.h
> index 053ae39..8fa1bfa 100644
> --- a/criu/include/page-pipe.h
> +++ b/criu/include/page-pipe.h
> @@ -102,12 +102,23 @@ struct page_pipe_buf {
>  	struct list_head l;	/* links into page_pipe->bufs */
>  };
>  
> +/*
> + * Page pipe buffers with different flags cannot share the same pipe.
> + * We track the last ppb that was used for each type separately in the
> + * prev[] array in the struct page_pipe (below).
> + * Currently we have 2 types: the buffers that are always stored in
> + * the images and the buffers that are lazily migrated
> + */
> +#define PP_PIPE_TYPES	2
> +
>  #define PP_HOLE_PARENT (1 << 0)
>  
>  struct page_pipe {
>  	unsigned int nr_pipes;	/* how many page_pipe_bufs in there */
>  	struct list_head bufs;	/* list of bufs */
>  	struct list_head free_bufs;	/* list of bufs */
> +	struct page_pipe_buf *prev[PP_PIPE_TYPES];	/* last ppb of each type
> +							   for pipe sharing */
>  	unsigned int nr_iovs;	/* number of iovs */
>  	unsigned int free_iov;	/* first free iov */
>  	struct iovec *iovs;	/* iovs. They are provided into create_page_pipe
> diff --git a/criu/page-pipe.c b/criu/page-pipe.c
> index f33e86a..f790a6f 100644
> --- a/criu/page-pipe.c
> +++ b/criu/page-pipe.c
> @@ -10,6 +10,7 @@
>  #include "page-pipe.h"
>  #include "fcntl.h"
>  #include "stats.h"
> +#include "cr_options.h"
>  
>  /* can existing iov accumulate the page? */
>  static inline bool iov_grow_page(struct iovec *iov, unsigned long addr)
> @@ -63,8 +64,39 @@ static inline int ppb_resize_pipe(struct page_pipe_buf *ppb)
>  	return 0;
>  }
>  
> -static struct page_pipe_buf *ppb_alloc(struct page_pipe *pp, struct page_pipe_buf *prev)
> +static struct page_pipe_buf *pp_prev_ppb(struct page_pipe *pp,
> +					 unsigned int ppb_flags)
>  {
> +	int type = 0;
> +
> +	/* don't allow to reuse a pipe in the PP_CHUNK_MODE mode */
> +	if (pp->flags & PP_CHUNK_MODE)
> +		return NULL;
> +
> +	if (list_empty(&pp->bufs))
> +		return NULL;
> +
> +	if (ppb_flags & PPB_LAZY && opts.lazy_pages)
> +		type = 1;
> +
> +	return pp->prev[type];
> +}
> +
> +static void pp_update_prev_ppb(struct page_pipe *pp, struct page_pipe_buf *ppb,
> +			       unsigned int ppb_flags)
> +{
> +	int type = 0;
> +
> +	if (ppb_flags & PPB_LAZY && opts.lazy_pages)
> +		type = 1;
> +
> +	pp->prev[type] = ppb;
> +}
> +
> +static struct page_pipe_buf *ppb_alloc(struct page_pipe *pp,
> +				       unsigned int ppb_flags)
> +{
> +	struct page_pipe_buf *prev = pp_prev_ppb(pp, ppb_flags);
>  	struct page_pipe_buf *ppb;
>  
>  	ppb = xmalloc(sizeof(*ppb));
> @@ -94,6 +126,8 @@ static struct page_pipe_buf *ppb_alloc(struct page_pipe *pp, struct page_pipe_bu
>  
>  	list_add_tail(&ppb->l, &pp->bufs);
>  
> +	pp_update_prev_ppb(pp, ppb, ppb_flags);
> +
>  	return ppb;
>  }
>  
> @@ -119,7 +153,7 @@ static void ppb_init(struct page_pipe_buf *ppb, unsigned int pages_in,
>  
>  static int page_pipe_grow(struct page_pipe *pp, unsigned int flags)
>  {
> -	struct page_pipe_buf *ppb, *prev = NULL;
> +	struct page_pipe_buf *ppb;
>  	struct iovec *free_iov;
>  
>  	pr_debug("Will grow page pipe (iov off is %u)\n", pp->free_iov);
> @@ -133,10 +167,7 @@ static int page_pipe_grow(struct page_pipe *pp, unsigned int flags)
>  	if ((pp->flags & PP_CHUNK_MODE) && (pp->nr_pipes == NR_PIPES_PER_CHUNK))
>  		return -EAGAIN;
>  
> -	/* don't allow to reuse a pipe in the PP_CHUNK_MODE mode */
> -	if (!(pp->flags & PP_CHUNK_MODE) && !list_empty(&pp->bufs))
> -		prev = list_entry(pp->bufs.prev, struct page_pipe_buf, l);
> -	ppb = ppb_alloc(pp, prev);
> +	ppb = ppb_alloc(pp, flags);
>  	if (!ppb)
>  		return -1;
>  
> -- 
> 2.7.4
> 


More information about the CRIU mailing list