mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-30 22:05:36 +00:00
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 <snorcht@gmail.com> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
committed by
Pavel Emelyanov
parent
8ed215d252
commit
32a48b67b7
35
cr-dedup.c
35
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;
|
||||
}
|
||||
|
@@ -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__ */
|
||||
|
14
page-read.c
14
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) {
|
||||
|
Reference in New Issue
Block a user