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

Tikhomirov Pavel snorcht at gmail.com
Fri Mar 7 01:01:47 PST 2014


when decide that data is no longer needed, there are two cases:
-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.
-if data not neighbours bunch block(or bunch block size will be bigger
than MAX_BUNCH_SIZE), than we punch bunch block and set bunch block
to curent block.

in the end make cleanup to punch last bunch block.

changes in v1:
punch_hole takes whole page_read
make restriction more precise

Signed-off-by: Tikhomirov Pavel <snorcht at gmail.com>
---
 cr-dedup.c          | 35 +++++++++++++++++++++++++++--------
 include/page-read.h |  4 +++-
 page-read.c         | 13 ++++++++++++-
 3 files changed, 42 insertions(+), 10 deletions(-)

diff --git a/cr-dedup.c b/cr-dedup.c
index 6f059d1..bca07fa 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,32 @@ exit:
 	return 0;
 }
 
-int punch_hole(int fd, unsigned long off, unsigned long len)
+int punch_hole(struct page_read *pr, unsigned long off, unsigned long len,
+	       bool cleanup)
 {
 	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;
+	struct iovec * bunch = &pr->bunch;
+
+	if ((unsigned long)bunch->iov_base + bunch->iov_len == off && !cleanup
+	    && (bunch->iov_len + len < MAX_BUNCH_SIZE * PAGE_SIZE
+	    || bunch->iov_len == 0)) {
+		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(pr->fd_pg, 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 +165,7 @@ 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, off_real, min(piov_end, iov_end) - off, false);
 			if (ret == -1)
 				return ret;
 		}
diff --git a/include/page-read.h b/include/page-read.h
index 8b467c6..9078eaa 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,5 @@ 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(struct page_read *pr, unsigned long off, unsigned long len, bool cleanup);
 #endif /* __CR_PAGE_READ_H__ */
diff --git a/page-read.c b/page-read.c
index e2514d6..f8c830d 100644
--- a/page-read.c
+++ b/page-read.c
@@ -149,7 +149,7 @@ 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, current_vaddr, (unsigned int)PAGE_SIZE, false);
 			if (ret == -1) {
 				return -1;
 			}
@@ -163,6 +163,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, 0, 0, true);
+		if (ret == -1)
+			return;
+
+		pr->bunch.iov_len = 0;
+	}
+
 	if (pr->parent) {
 		close_page_read(pr->parent);
 		xfree(pr->parent);
@@ -207,6 +216,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) {
-- 
1.8.3.2



More information about the CRIU mailing list