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 "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:
|
|||||||
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)
|
|||||||
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 {
|
|||||||
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);
|
|||||||
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__ */
|
||||||
|
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) {
|
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
|
|||||||
|
|
||||||
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:
|
|||||||
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) {
|
||||||
|
Reference in New Issue
Block a user