<div dir="ltr">It&#39;s not ready yet, found that it has some unexpected behavior...</div><div class="gmail_extra"><br clear="all"><div><div dir="ltr"><br>Best Regards, Tikhomirov Pavel.</div></div>
<br><br><div class="gmail_quote">2014-03-31 14:24 GMT+04:00 Tikhomirov Pavel <span dir="ltr">&lt;<a href="mailto:snorcht@gmail.com" target="_blank">snorcht@gmail.com</a>&gt;</span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
add evaddr in page_read to identify the end of curently checked area<br>
of pagemap entry, and then if we seek through(pass by) some part of<br>
pagemap entry, we assume this part(piece from evaddr) as unmaped<br>
in newer image, so we can dedup it in parent<br>
<br>
Example:<br>
2 --data--|---- -unmaped -----|--data--<br>
1 ----data ----|--data--|----- data----<br>
  cccccccc euuu euuuuuuu euuuu cccccccc<br>
c - stands for checked page, e and u - page for deduplication on<br>
unmap(e - evaddr)<br>
<br>
test: this patch make all images of size 0 in:<br>
sudo bash test/zdtm.sh --auto-dedup -P -i 10  transition/maps007<br>
<br>
Signed-off-by: Tikhomirov Pavel &lt;<a href="mailto:snorcht@gmail.com">snorcht@gmail.com</a>&gt;<br>
---<br>
 cr-dedup.c          | 17 +++++++++++++++++<br>
 include/page-read.h |  4 ++++<br>
 page-read.c         | 29 +++++++++++++++++++++++++++++<br>
 page-xfer.c         |  6 +++++-<br>
 4 files changed, 55 insertions(+), 1 deletion(-)<br>
<br>
diff --git a/cr-dedup.c b/cr-dedup.c<br>
index 7758674..9a485b3 100644<br>
--- a/cr-dedup.c<br>
+++ b/cr-dedup.c<br>
@@ -87,6 +87,18 @@ static int cr_dedup_one_pagemap(int pid)<br>
                        ret = dedup_one_iovec(prp, &amp;iov);<br>
                        if (ret)<br>
                                goto exit;<br>
+               } else {<br>
+                       /*<br>
+                        * If data is in parent go check it, check will use<br>
+                        * seek_pagemap_page, it starts deduplication of<br>
+                        * passed by unmaped areas<br>
+                        */<br>
+                       ret = check_pagehole_in_parent(prp, &amp;iov);<br>
+                       if (ret) {<br>
+                               pr_err(&quot;Hole %p/%zu not found in parent\n&quot;,<br>
+                                      iov.iov_base, iov.iov_len);<br>
+                               goto exit;<br>
+                       }<br>
                }<br>
<br>
                pr.put_pagemap(&amp;pr);<br>
@@ -176,6 +188,11 @@ int dedup_one_iovec(struct page_read *pr, struct iovec *iov)<br>
                                return ret;<br>
                }<br>
<br>
+               /*<br>
+                * set evaddr to the end of checked area<br>
+                */<br>
+               pr-&gt;evaddr = min(piov_end, iov_end);<br>
+<br>
                prp = pr-&gt;parent;<br>
                if (prp) {<br>
                        /* recursively */<br>
diff --git a/include/page-read.h b/include/page-read.h<br>
index 7a063e9..1dc993f 100644<br>
--- a/include/page-read.h<br>
+++ b/include/page-read.h<br>
@@ -62,6 +62,9 @@ struct page_read {<br>
                                           go to this guy for page, see<br>
                                           read_pagemap_page */<br>
        unsigned long cvaddr;           /* vaddr we are on */<br>
+       unsigned long evaddr;           /* vaddr of the end of checked area<br>
+                                          need this to know what part of<br>
+                                          pagemap is unmounted */<br>
<br>
        struct iovec bunch;             /* record consequent neighbour<br>
                                           iovecs to punch together */<br>
@@ -75,4 +78,5 @@ extern int seek_pagemap_page(struct page_read *pr, unsigned long vaddr, bool war<br>
<br>
 extern int dedup_one_iovec(struct page_read *pr, struct iovec *iov);<br>
 extern int punch_hole(struct page_read *pr, unsigned long off, unsigned long len, bool cleanup);<br>
+extern int check_pagehole_in_parent(struct page_read *p, struct iovec *iov);<br>
 #endif /* __CR_PAGE_READ_H__ */<br>
diff --git a/page-read.c b/page-read.c<br>
index 8937f33..aab9efe 100644<br>
--- a/page-read.c<br>
+++ b/page-read.c<br>
@@ -62,6 +62,7 @@ static int get_pagemap(struct page_read *pr, struct iovec *iov)<br>
<br>
        pr-&gt;pe = pe;<br>
        pr-&gt;cvaddr = (unsigned long)iov-&gt;iov_base;<br>
+       pr-&gt;evaddr = (unsigned long)iov-&gt;iov_base;<br>
<br>
        if (pe-&gt;in_parent &amp;&amp; !pr-&gt;parent) {<br>
                pr_err(&quot;No parent for snapshot pagemap\n&quot;);<br>
@@ -87,6 +88,7 @@ static void skip_pagemap_pages(struct page_read *pr, unsigned long len)<br>
        if (!pr-&gt;pe-&gt;in_parent)<br>
                lseek(pr-&gt;fd_pg, len, SEEK_CUR);<br>
        pr-&gt;cvaddr += len;<br>
+       pr-&gt;evaddr += len;<br>
 }<br>
<br>
 int seek_pagemap_page(struct page_read *pr, unsigned long vaddr, bool warn)<br>
@@ -101,6 +103,7 @@ int seek_pagemap_page(struct page_read *pr, unsigned long vaddr, bool warn)<br>
<br>
        while (1) {<br>
                unsigned long iov_end;<br>
+               struct iovec tiov;<br>
<br>
                if (vaddr &lt; pr-&gt;cvaddr) {<br>
                        if (warn)<br>
@@ -111,6 +114,19 @@ int seek_pagemap_page(struct page_read *pr, unsigned long vaddr, bool warn)<br>
                iov_end = (unsigned long)iov.iov_base + iov.iov_len;<br>
<br>
                if (iov_end &lt;= vaddr) {<br>
+                       /*<br>
+                        * If pass by pagemap entry in parent, it was unmaped so we can dedup it<br>
+                        * pr-&gt;evaddr is used to identify end of previously checked region<br>
+                        */<br>
+                       if (opts.auto_dedup) {<br>
+                               tiov.iov_base = (void*)pr-&gt;evaddr;<br>
+                               tiov.iov_len = iov_end - pr-&gt;evaddr;<br>
+                               if (tiov.iov_len &gt; 0) {<br>
+                                       pr_debug(&quot;pr%d: Assume(1) unmaped vma from %lx len %lx\n&quot;, pr-&gt;id, pr-&gt;evaddr, tiov.iov_len);<br>
+                                       dedup_one_iovec(pr, &amp;tiov);<br>
+                               }<br>
+                       }<br>
+<br>
                        skip_pagemap_pages(pr, iov_end - pr-&gt;cvaddr);<br>
                        put_pagemap(pr);<br>
 new_pagemap:<br>
@@ -120,6 +136,18 @@ new_pagemap:<br>
<br>
                        continue;<br>
                }<br>
+<br>
+               /*<br>
+                * If pass by part of pagemap entry in parent, it was unmaped<br>
+                */<br>
+               if (opts.auto_dedup) {<br>
+                       tiov.iov_base = (void*)pr-&gt;evaddr;<br>
+                       tiov.iov_len = vaddr - pr-&gt;evaddr;<br>
+                       if (tiov.iov_len &gt; 0) {<br>
+                               pr_debug(&quot;pr%d: Assume(2) unmaped vma from %lx len %lx\n&quot;, pr-&gt;id, pr-&gt;evaddr, tiov.iov_len);<br>
+                               dedup_one_iovec(pr, &amp;tiov);<br>
+                       }<br>
+               }<br>
<br>
                skip_pagemap_pages(pr, vaddr - pr-&gt;cvaddr);<br>
                return 1;<br>
@@ -157,6 +185,7 @@ static int read_pagemap_page(struct page_read *pr, unsigned long vaddr, void *bu<br>
        }<br>
<br>
        pr-&gt;cvaddr += PAGE_SIZE;<br>
+       pr-&gt;evaddr += PAGE_SIZE;<br>
<br>
        return 1;<br>
 }<br>
diff --git a/page-xfer.c b/page-xfer.c<br>
index f26be35..c63bec2 100644<br>
--- a/page-xfer.c<br>
+++ b/page-xfer.c<br>
@@ -487,7 +487,7 @@ static int write_pages_loc(struct page_xfer *xfer,<br>
        return 0;<br>
 }<br>
<br>
-static int check_pagehole_in_parent(struct page_read *p, struct iovec *iov)<br>
+int check_pagehole_in_parent(struct page_read *p, struct iovec *iov)<br>
 {<br>
        int ret;<br>
        unsigned long off, end;<br>
@@ -521,6 +521,10 @@ static int check_pagehole_in_parent(struct page_read *p, struct iovec *iov)<br>
                 */<br>
<br>
                pend = (unsigned long)piov.iov_base + piov.iov_len;<br>
+               /*<br>
+                * Set evaddr to the end of checked area<br>
+                */<br>
+               p-&gt;evaddr = min(pend, end);<br>
                if (end &lt;= pend)<br>
                        return 0;<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
1.8.3.2<br>
<br>
</font></span></blockquote></div><br></div>