[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