<div dir="ltr">It'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"><<a href="mailto:snorcht@gmail.com" target="_blank">snorcht@gmail.com</a>></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 <<a href="mailto:snorcht@gmail.com">snorcht@gmail.com</a>><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, &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, &iov);<br>
+ if (ret) {<br>
+ pr_err("Hole %p/%zu not found in parent\n",<br>
+ iov.iov_base, iov.iov_len);<br>
+ goto exit;<br>
+ }<br>
}<br>
<br>
pr.put_pagemap(&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->evaddr = min(piov_end, iov_end);<br>
+<br>
prp = pr->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->pe = pe;<br>
pr->cvaddr = (unsigned long)iov->iov_base;<br>
+ pr->evaddr = (unsigned long)iov->iov_base;<br>
<br>
if (pe->in_parent && !pr->parent) {<br>
pr_err("No parent for snapshot pagemap\n");<br>
@@ -87,6 +88,7 @@ static void skip_pagemap_pages(struct page_read *pr, unsigned long len)<br>
if (!pr->pe->in_parent)<br>
lseek(pr->fd_pg, len, SEEK_CUR);<br>
pr->cvaddr += len;<br>
+ pr->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 < pr->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 <= vaddr) {<br>
+ /*<br>
+ * If pass by pagemap entry in parent, it was unmaped so we can dedup it<br>
+ * pr->evaddr is used to identify end of previously checked region<br>
+ */<br>
+ if (opts.auto_dedup) {<br>
+ tiov.iov_base = (void*)pr->evaddr;<br>
+ tiov.iov_len = iov_end - pr->evaddr;<br>
+ if (tiov.iov_len > 0) {<br>
+ pr_debug("pr%d: Assume(1) unmaped vma from %lx len %lx\n", pr->id, pr->evaddr, tiov.iov_len);<br>
+ dedup_one_iovec(pr, &tiov);<br>
+ }<br>
+ }<br>
+<br>
skip_pagemap_pages(pr, iov_end - pr->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->evaddr;<br>
+ tiov.iov_len = vaddr - pr->evaddr;<br>
+ if (tiov.iov_len > 0) {<br>
+ pr_debug("pr%d: Assume(2) unmaped vma from %lx len %lx\n", pr->id, pr->evaddr, tiov.iov_len);<br>
+ dedup_one_iovec(pr, &tiov);<br>
+ }<br>
+ }<br>
<br>
skip_pagemap_pages(pr, vaddr - pr->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->cvaddr += PAGE_SIZE;<br>
+ pr->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->evaddr = min(pend, end);<br>
if (end <= 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>