[CRIU] [PATCH] deduplication: bunch neighbour data to punch together

Pavel Emelyanov xemul at parallels.com
Tue Mar 4 10:06:36 PST 2014


On 03/03/2014 05:51 PM, Tikhomirov Pavel wrote:
> when decide that data is no longer needed, there are two cases:
> 1. if data neighbours previous block of "no needed" data, extend bunch
> block(it holds begining and size of concequent "no needed" data) by
> length of curent block and go next.
> 2. if data not neighbours bunch block(or bunch block size is bigger
> than MAX_BUNCH_SIZE), than punch bunch block and set bunch block
> to curent block.
> 
> in the end make cleanup to punch last bunch block.
> 
> Signed-off-by: Tikhomirov Pavel <snorcht at gmail.com>
> ---
>  cr-dedup.c          | 34 ++++++++++++++++++++++++++--------
>  include/page-read.h |  5 ++++-
>  page-read.c         | 14 +++++++++++++-
>  3 files changed, 43 insertions(+), 10 deletions(-)
> 
> diff --git a/cr-dedup.c b/cr-dedup.c
> index 6f059d1..9d269d2 100644
> --- a/cr-dedup.c
> +++ b/cr-dedup.c
> @@ -7,6 +7,8 @@
>  #include "page-read.h"
>  #include "restorer.h"
>  
> +#define MAX_BUNCH_SIZE 256
> +
>  static int cr_dedup_one_pagemap(int pid);
>  
>  int cr_dedup(void)
> @@ -101,15 +103,30 @@ exit:
>  	return 0;
>  }
>  
> -int punch_hole(int fd, unsigned long off, unsigned long len)
> +int punch_hole(int fd, unsigned long off, unsigned long len,
> +	       struct iovec * bunch, bool cleanup, int pr_id)

Make punch_hole() accept the whole page_read object, you anyway
push there 3 its members.

>  {
>  	int ret;
> -	pr_debug("Punch!/%lu/%lu/\n", off, len);
> -	ret = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
> -			off, len);
> -	if (ret != 0) {
> -		pr_perror("Error punching hole");
> -		return -1;
> +
> +	if ((unsigned long)bunch->iov_base + bunch->iov_len == off && !cleanup
> +	    && bunch->iov_len < MAX_BUNCH_SIZE * PAGE_SIZE) {

You should check that the resulting iov_len fits the MAX_BUNCH_SIZE, not current.

> +		pr_debug("pr%d:Extend bunch len from %lx to %lx\n", pr_id,
> +			 bunch->iov_len, bunch->iov_len + len);
> +		bunch->iov_len += len;
> +	} else {
> +		if (bunch->iov_len > 0) {
> +			pr_debug("Punch!/%lx/%lx/\n", (unsigned long)bunch->iov_base, bunch->iov_len);
> +			ret = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
> +					(unsigned long)bunch->iov_base, bunch->iov_len);
> +			if (ret != 0) {
> +				pr_perror("Error punching hole");
> +				return -1;
> +			}
> +		}
> +		bunch->iov_base = (void *)off;
> +		bunch->iov_len = len;
> +		pr_debug("pr%d:New bunch/%lx/%lx/\n", pr_id,
> +			 (unsigned long)bunch->iov_base, bunch->iov_len);
>  	}
>  	return 0;
>  }
> @@ -146,7 +163,8 @@ int dedup_one_iovec(struct page_read *pr, struct iovec *iov)
>  		piov_end = (unsigned long)piov.iov_base + piov.iov_len;
>  		off_real = lseek(pr->fd_pg, 0, SEEK_CUR);
>  		if (!pr->pe->in_parent) {
> -			ret = punch_hole(pr->fd_pg, off_real, min(piov_end, iov_end) - off);
> +			ret = punch_hole(pr->fd_pg, off_real, min(piov_end, iov_end) - off,
> +				         &pr->bunch, false, pr->id);
>  			if (ret == -1)
>  				return ret;
>  		}
> diff --git a/include/page-read.h b/include/page-read.h
> index 8b467c6..28435c7 100644
> --- a/include/page-read.h
> +++ b/include/page-read.h
> @@ -63,6 +63,8 @@ struct page_read {
>  					   read_pagemap_page */
>  	unsigned long cvaddr;		/* vaddr we are on */
>  
> +	struct iovec bunch;		/* record consequent neighbour
> +					   iovecs to punch together */
>  	unsigned id; /* for logging */
>  };
>  
> @@ -72,5 +74,6 @@ extern void pagemap2iovec(PagemapEntry *pe, struct iovec *iov);
>  extern int seek_pagemap_page(struct page_read *pr, unsigned long vaddr, bool warn);
>  
>  extern int dedup_one_iovec(struct page_read *pr, struct iovec *iov);
> -extern int punch_hole(int fd, unsigned long off, unsigned long len);
> +extern int punch_hole(int fd, unsigned long off, unsigned long len,
> +		      struct iovec * bunch, bool cleanup, int pr_id);
>  #endif /* __CR_PAGE_READ_H__ */
> diff --git a/page-read.c b/page-read.c
> index e2514d6..0fd3464 100644
> --- a/page-read.c
> +++ b/page-read.c
> @@ -149,7 +149,8 @@ static int read_pagemap_page(struct page_read *pr, unsigned long vaddr, void *bu
>  		}
>  
>  		if (opts.auto_dedup) {
> -			ret = punch_hole(pr->fd_pg, current_vaddr, (unsigned int)PAGE_SIZE);
> +			ret = punch_hole(pr->fd_pg, current_vaddr, (unsigned int)PAGE_SIZE,
> +					 &pr->bunch, false, pr->id);
>  			if (ret == -1) {
>  				return -1;
>  			}
> @@ -163,6 +164,15 @@ static int read_pagemap_page(struct page_read *pr, unsigned long vaddr, void *bu
>  
>  static void close_page_read(struct page_read *pr)
>  {
> +	int ret;
> +	if (pr->bunch.iov_len > 0) {
> +		ret = punch_hole(pr->fd_pg, 0, 0, &pr->bunch, true, pr->id);
> +		if (ret == -1)
> +			return;
> +
> +		pr->bunch.iov_len = 0;
> +	}
> +
>  	if (pr->parent) {
>  		close_page_read(pr->parent);
>  		xfree(pr->parent);
> @@ -207,6 +217,8 @@ err_cl:
>  int open_page_read_at(int dfd, int pid, struct page_read *pr, int flags)
>  {
>  	pr->pe = NULL;
> +	pr->bunch.iov_len = 0;
> +	pr->bunch.iov_base = NULL;
>  
>  	pr->fd = open_image_at(dfd, CR_FD_PAGEMAP, O_RSTR, (long)pid);
>  	if (pr->fd < 0) {
> 




More information about the CRIU mailing list