[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