Commit 32a48b67 authored by Tikhomirov Pavel's avatar Tikhomirov Pavel Committed by Pavel Emelyanov

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: 's avatarTikhomirov Pavel <snorcht@gmail.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 8ed215d2
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include "page-read.h" #include "page-read.h"
#include "restorer.h" #include "restorer.h"
#define MAX_BUNCH_SIZE 256
static int cr_dedup_one_pagemap(int pid); static int cr_dedup_one_pagemap(int pid);
int cr_dedup(void) int cr_dedup(void)
...@@ -101,15 +103,32 @@ exit: ...@@ -101,15 +103,32 @@ exit:
return 0; 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; int ret;
pr_debug("Punch!/%lu/%lu/\n", off, len); struct iovec * bunch = &pr->bunch;
ret = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
off, len); if ((unsigned long)bunch->iov_base + bunch->iov_len == off && !cleanup
if (ret != 0) { && (bunch->iov_len + len < MAX_BUNCH_SIZE * PAGE_SIZE
pr_perror("Error punching hole"); || bunch->iov_len == 0)) {
return -1; 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; return 0;
} }
...@@ -146,7 +165,7 @@ int dedup_one_iovec(struct page_read *pr, struct iovec *iov) ...@@ -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; piov_end = (unsigned long)piov.iov_base + piov.iov_len;
off_real = lseek(pr->fd_pg, 0, SEEK_CUR); off_real = lseek(pr->fd_pg, 0, SEEK_CUR);
if (!pr->pe->in_parent) { 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) if (ret == -1)
return ret; return ret;
} }
......
...@@ -63,6 +63,8 @@ struct page_read { ...@@ -63,6 +63,8 @@ struct page_read {
read_pagemap_page */ read_pagemap_page */
unsigned long cvaddr; /* vaddr we are on */ unsigned long cvaddr; /* vaddr we are on */
struct iovec bunch; /* record consequent neighbour
iovecs to punch together */
unsigned id; /* for logging */ unsigned id; /* for logging */
}; };
...@@ -72,5 +74,5 @@ extern void pagemap2iovec(PagemapEntry *pe, struct iovec *iov); ...@@ -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 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 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__ */ #endif /* __CR_PAGE_READ_H__ */
...@@ -149,7 +149,7 @@ static int read_pagemap_page(struct page_read *pr, unsigned long vaddr, void *bu ...@@ -149,7 +149,7 @@ static int read_pagemap_page(struct page_read *pr, unsigned long vaddr, void *bu
} }
if (opts.auto_dedup) { 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) { if (ret == -1) {
return -1; return -1;
} }
...@@ -163,6 +163,16 @@ static int read_pagemap_page(struct page_read *pr, unsigned long vaddr, void *bu ...@@ -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) 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) { if (pr->parent) {
close_page_read(pr->parent); close_page_read(pr->parent);
xfree(pr->parent); xfree(pr->parent);
...@@ -207,6 +217,8 @@ err_cl: ...@@ -207,6 +217,8 @@ err_cl:
int open_page_read_at(int dfd, int pid, struct page_read *pr, int flags) int open_page_read_at(int dfd, int pid, struct page_read *pr, int flags)
{ {
pr->pe = NULL; 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); pr->fd = open_image_at(dfd, CR_FD_PAGEMAP, O_RSTR, (long)pid);
if (pr->fd < 0) { if (pr->fd < 0) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment