From 32a48b67b73b87d66a56c55725c6737d625ead27 Mon Sep 17 00:00:00 2001 From: Tikhomirov Pavel Date: Fri, 7 Mar 2014 14:31:29 +0400 Subject: [PATCH] v2 deduplication: bunch neighbour data to punch together 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 Signed-off-by: Pavel Emelyanov --- cr-dedup.c | 35 +++++++++++++++++++++++++++-------- include/page-read.h | 4 +++- page-read.c | 14 +++++++++++++- 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/cr-dedup.c b/cr-dedup.c index 6f059d148..bca07fa0e 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 8b467c61b..9078eaa63 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 e2514d613..fc51b6ae4 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,16 @@ 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 +217,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) {