Commit d866bd19 authored by Tikhomirov Pavel's avatar Tikhomirov Pavel Committed by Pavel Emelyanov

v3 deduplication: look up for old pages in previous snapshot

old snapshot from "parent" symlink, and pids from pagemap-PID.img files
Signed-off-by: 's avatarTikhomirov Pavel <snorcht@gmail.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent ea403c7a
#include <sys/uio.h>
#include <unistd.h>
#include "crtools.h"
#include "page-read.h"
#include "restorer.h"
int cr_dedup_one_pagemap(int pid);
int cr_dedup(void)
{
int close_ret, ret = 0;
int pid;
DIR * dirp;
struct dirent *ent;
dirp = opendir(CR_PARENT_LINK);
if (dirp == NULL) {
pr_perror("Can't enter previous snapshot folder, error=%d", errno);
ret = -1;
goto err;
}
while (1) {
errno = 0;
ent = readdir(dirp);
if (ent == NULL) {
if (errno) {
pr_perror("Failed readdir, error=%d", errno);
ret = -1;
goto err;
}
break;
}
ret = sscanf(ent->d_name, "pagemap-%d.img", &pid);
if (ret == 1) {
pr_info("pid=%d\n", pid);
ret = cr_dedup_one_pagemap(pid);
if (ret < 0)
break;
}
}
err:
if (dirp) {
close_ret = closedir(dirp);
if (close_ret == -1)
return close_ret;
}
if (ret < 0)
return ret;
pr_info("Deduplicated\n");
return 0;
}
int cr_dedup_one_pagemap(int pid)
{
int ret;
struct page_read pr;
struct page_read * prp;
struct iovec iov;
ret = open_page_rw(pid, &pr);
if (ret) {
ret = -1;
goto exit;
}
prp = pr.parent;
if (!prp)
goto exit;
ret = pr.get_pagemap(&pr, &iov);
if (ret <= 0)
goto exit;
while (1) {
pr_debug("dedup iovec base=%lu, len=%lu\n", (unsigned long)iov.iov_base, iov.iov_len);
if (!pr.pe->in_parent) {
ret = dedup_one_iovec(prp, &iov);
if (ret)
goto exit;
}
pr.put_pagemap(&pr);
ret = pr.get_pagemap(&pr, &iov);
if (ret <= 0)
goto exit;
}
exit:
pr.close(&pr);
if (ret < 0)
return ret;
return 0;
}
int dedup_one_iovec(struct page_read *pr, struct iovec *iov)
{
unsigned long off;
unsigned long iov_end;
iov_end = (unsigned long)iov->iov_base + iov->iov_len;
off = (unsigned long)iov->iov_base;
while (1) {
int ret;
struct iovec piov;
unsigned long piov_end;
ret = seek_pagemap_page(pr, off, false);
if (ret == -1) {
if(off < pr->cvaddr) {
if(pr->cvaddr < iov_end)
off = pr->cvaddr;
else
return 0;
} else
return ret;
}
if (!pr->pe)
return -1;
pagemap2iovec(pr->pe, &piov);
piov_end = (unsigned long)piov.iov_base + piov.iov_len;
if (piov_end < iov_end) {
off = piov_end;
continue;
} else
return 0;
}
return 0;
}
......@@ -70,4 +70,6 @@ extern int open_page_read(int pid, struct page_read *);
extern int open_page_rw(int pid, struct page_read *);
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);
#endif /* __CR_PAGE_READ_H__ */
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