[CRIU] [PATCH] dedup: add dedup on unmap vma, into auto-dedup and dedup

Pavel Tikhomirov snorcht at gmail.com
Fri Apr 4 02:15:01 PDT 2014


It's not ready yet, found that it has some unexpected behavior...


Best Regards, Tikhomirov Pavel.


2014-03-31 14:24 GMT+04:00 Tikhomirov Pavel <snorcht at gmail.com>:

> add evaddr in page_read to identify the end of curently checked area
> of pagemap entry, and then if we seek through(pass by) some part of
> pagemap entry, we assume this part(piece from evaddr) as unmaped
> in newer image, so we can dedup it in parent
>
> Example:
> 2 --data--|---- -unmaped -----|--data--
> 1 ----data ----|--data--|----- data----
>   cccccccc euuu euuuuuuu euuuu cccccccc
> c - stands for checked page, e and u - page for deduplication on
> unmap(e - evaddr)
>
> test: this patch make all images of size 0 in:
> sudo bash test/zdtm.sh --auto-dedup -P -i 10  transition/maps007
>
> Signed-off-by: Tikhomirov Pavel <snorcht at gmail.com>
> ---
>  cr-dedup.c          | 17 +++++++++++++++++
>  include/page-read.h |  4 ++++
>  page-read.c         | 29 +++++++++++++++++++++++++++++
>  page-xfer.c         |  6 +++++-
>  4 files changed, 55 insertions(+), 1 deletion(-)
>
> diff --git a/cr-dedup.c b/cr-dedup.c
> index 7758674..9a485b3 100644
> --- a/cr-dedup.c
> +++ b/cr-dedup.c
> @@ -87,6 +87,18 @@ static int cr_dedup_one_pagemap(int pid)
>                         ret = dedup_one_iovec(prp, &iov);
>                         if (ret)
>                                 goto exit;
> +               } else {
> +                       /*
> +                        * If data is in parent go check it, check will use
> +                        * seek_pagemap_page, it starts deduplication of
> +                        * passed by unmaped areas
> +                        */
> +                       ret = check_pagehole_in_parent(prp, &iov);
> +                       if (ret) {
> +                               pr_err("Hole %p/%zu not found in parent\n",
> +                                      iov.iov_base, iov.iov_len);
> +                               goto exit;
> +                       }
>                 }
>
>                 pr.put_pagemap(&pr);
> @@ -176,6 +188,11 @@ int dedup_one_iovec(struct page_read *pr, struct
> iovec *iov)
>                                 return ret;
>                 }
>
> +               /*
> +                * set evaddr to the end of checked area
> +                */
> +               pr->evaddr = min(piov_end, iov_end);
> +
>                 prp = pr->parent;
>                 if (prp) {
>                         /* recursively */
> diff --git a/include/page-read.h b/include/page-read.h
> index 7a063e9..1dc993f 100644
> --- a/include/page-read.h
> +++ b/include/page-read.h
> @@ -62,6 +62,9 @@ struct page_read {
>                                            go to this guy for page, see
>                                            read_pagemap_page */
>         unsigned long cvaddr;           /* vaddr we are on */
> +       unsigned long evaddr;           /* vaddr of the end of checked area
> +                                          need this to know what part of
> +                                          pagemap is unmounted */
>
>         struct iovec bunch;             /* record consequent neighbour
>                                            iovecs to punch together */
> @@ -75,4 +78,5 @@ extern int seek_pagemap_page(struct page_read *pr,
> unsigned long vaddr, bool war
>
>  extern int dedup_one_iovec(struct page_read *pr, struct iovec *iov);
>  extern int punch_hole(struct page_read *pr, unsigned long off, unsigned
> long len, bool cleanup);
> +extern int check_pagehole_in_parent(struct page_read *p, struct iovec
> *iov);
>  #endif /* __CR_PAGE_READ_H__ */
> diff --git a/page-read.c b/page-read.c
> index 8937f33..aab9efe 100644
> --- a/page-read.c
> +++ b/page-read.c
> @@ -62,6 +62,7 @@ static int get_pagemap(struct page_read *pr, struct
> iovec *iov)
>
>         pr->pe = pe;
>         pr->cvaddr = (unsigned long)iov->iov_base;
> +       pr->evaddr = (unsigned long)iov->iov_base;
>
>         if (pe->in_parent && !pr->parent) {
>                 pr_err("No parent for snapshot pagemap\n");
> @@ -87,6 +88,7 @@ static void skip_pagemap_pages(struct page_read *pr,
> unsigned long len)
>         if (!pr->pe->in_parent)
>                 lseek(pr->fd_pg, len, SEEK_CUR);
>         pr->cvaddr += len;
> +       pr->evaddr += len;
>  }
>
>  int seek_pagemap_page(struct page_read *pr, unsigned long vaddr, bool
> warn)
> @@ -101,6 +103,7 @@ int seek_pagemap_page(struct page_read *pr, unsigned
> long vaddr, bool warn)
>
>         while (1) {
>                 unsigned long iov_end;
> +               struct iovec tiov;
>
>                 if (vaddr < pr->cvaddr) {
>                         if (warn)
> @@ -111,6 +114,19 @@ int seek_pagemap_page(struct page_read *pr, unsigned
> long vaddr, bool warn)
>                 iov_end = (unsigned long)iov.iov_base + iov.iov_len;
>
>                 if (iov_end <= vaddr) {
> +                       /*
> +                        * If pass by pagemap entry in parent, it was
> unmaped so we can dedup it
> +                        * pr->evaddr is used to identify end of
> previously checked region
> +                        */
> +                       if (opts.auto_dedup) {
> +                               tiov.iov_base = (void*)pr->evaddr;
> +                               tiov.iov_len = iov_end - pr->evaddr;
> +                               if (tiov.iov_len > 0) {
> +                                       pr_debug("pr%d: Assume(1) unmaped
> vma from %lx len %lx\n", pr->id, pr->evaddr, tiov.iov_len);
> +                                       dedup_one_iovec(pr, &tiov);
> +                               }
> +                       }
> +
>                         skip_pagemap_pages(pr, iov_end - pr->cvaddr);
>                         put_pagemap(pr);
>  new_pagemap:
> @@ -120,6 +136,18 @@ new_pagemap:
>
>                         continue;
>                 }
> +
> +               /*
> +                * If pass by part of pagemap entry in parent, it was
> unmaped
> +                */
> +               if (opts.auto_dedup) {
> +                       tiov.iov_base = (void*)pr->evaddr;
> +                       tiov.iov_len = vaddr - pr->evaddr;
> +                       if (tiov.iov_len > 0) {
> +                               pr_debug("pr%d: Assume(2) unmaped vma from
> %lx len %lx\n", pr->id, pr->evaddr, tiov.iov_len);
> +                               dedup_one_iovec(pr, &tiov);
> +                       }
> +               }
>
>                 skip_pagemap_pages(pr, vaddr - pr->cvaddr);
>                 return 1;
> @@ -157,6 +185,7 @@ static int read_pagemap_page(struct page_read *pr,
> unsigned long vaddr, void *bu
>         }
>
>         pr->cvaddr += PAGE_SIZE;
> +       pr->evaddr += PAGE_SIZE;
>
>         return 1;
>  }
> diff --git a/page-xfer.c b/page-xfer.c
> index f26be35..c63bec2 100644
> --- a/page-xfer.c
> +++ b/page-xfer.c
> @@ -487,7 +487,7 @@ static int write_pages_loc(struct page_xfer *xfer,
>         return 0;
>  }
>
> -static int check_pagehole_in_parent(struct page_read *p, struct iovec
> *iov)
> +int check_pagehole_in_parent(struct page_read *p, struct iovec *iov)
>  {
>         int ret;
>         unsigned long off, end;
> @@ -521,6 +521,10 @@ static int check_pagehole_in_parent(struct page_read
> *p, struct iovec *iov)
>                  */
>
>                 pend = (unsigned long)piov.iov_base + piov.iov_len;
> +               /*
> +                * Set evaddr to the end of checked area
> +                */
> +               p->evaddr = min(pend, end);
>                 if (end <= pend)
>                         return 0;
>
> --
> 1.8.3.2
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openvz.org/pipermail/criu/attachments/20140404/4f2952a6/attachment-0001.html>


More information about the CRIU mailing list