[CRIU] [PATCH 06/10] deduplication: look up for old pages in previous snapshot
Tikhomirov Pavel
snorcht at gmail.com
Tue Nov 19 02:28:25 PST 2013
old snapshot from "parent" symlink, and pids from pagemap-PID.img files
Signed-off-by: Tikhomirov Pavel <snorcht at gmail.com>
---
cr-dedup.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++
include/page-read.h | 1 +
page-read.c | 24 ++++++++---
3 files changed, 135 insertions(+), 7 deletions(-)
diff --git a/cr-dedup.c b/cr-dedup.c
index 225ab2d..a8df351 100644
--- a/cr-dedup.c
+++ b/cr-dedup.c
@@ -1,8 +1,125 @@
#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_err("Can't enter previous snapshot folder, error=%d\n", errno);
+ ret = -1;
+ goto err;
+ }
+
+ while (1) {
+ errno = 0;
+ ent = readdir(dirp);
+ if (ent == NULL) {
+ if (errno) {
+ pr_err("Failed readdir, error=%d\n", 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;
+ unsigned long off, off_real = 0;
+ 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;
+
+ off = (unsigned long)iov.iov_base;
+ while (1) {
+ unsigned long iov_end, piov_end;
+ struct iovec piov;
+
+ iov_end = (unsigned long)iov.iov_base + iov.iov_len;
+
+ ret = seek_pagemap_page(prp, off, DO_NOT_PRINT_ERROR);
+ if (ret == -1) {
+ if (off < prp->cvaddr)
+ if (prp->cvaddr < iov_end)
+ off = prp->cvaddr;
+ else
+ goto new_pagemap;
+ else
+ goto exit;
+ }
+
+ if (prp->pe)
+ pagemap2iovec(prp->pe, &piov);
+ piov_end = (unsigned long)piov.iov_base + piov.iov_len;
+ off_real = lseek(prp->fd_pg, 0, SEEK_CUR);
+
+ /*Here to punch that pagemap*/
+
+ if (piov_end < iov_end) {
+ off = piov_end;
+ continue;
+ }
+new_pagemap:
+ pr.put_pagemap(&pr);
+
+ ret = pr.get_pagemap(&pr, &iov);
+ if (ret <= 0)
+ goto exit;
+
+ off = (unsigned long)iov.iov_base;
+ }
+exit:
+ pr.close(&pr);
+
+ if (ret < 0)
+ return ret;
+
return 0;
}
diff --git a/include/page-read.h b/include/page-read.h
index 231877a..5da9d86 100644
--- a/include/page-read.h
+++ b/include/page-read.h
@@ -66,6 +66,7 @@ struct page_read {
};
int open_page_read(int pid, struct page_read *);
+int open_page_rw(int pid, struct page_read *);
inline void pagemap2iovec(PagemapEntry *pe, struct iovec *iov);
int seek_pagemap_page(struct page_read *pr, unsigned long vaddr, int flags);
diff --git a/page-read.c b/page-read.c
index 4fe6b86..1d51e90 100644
--- a/page-read.c
+++ b/page-read.c
@@ -158,9 +158,9 @@ static void close_page_read(struct page_read *pr)
close(pr->fd);
}
-static int open_page_read_at(int dfd, int pid, struct page_read *pr);
+static int open_page_at(int dfd, int pid, struct page_read *pr, int flags);
-static int try_open_parent(int dfd, int pid, struct page_read *pr)
+static int try_open_parent(int dfd, int pid, struct page_read *pr, int flags)
{
int pfd;
struct page_read *parent = NULL;
@@ -173,7 +173,7 @@ static int try_open_parent(int dfd, int pid, struct page_read *pr)
if (!parent)
goto err_cl;
- if (open_page_read_at(pfd, pid, parent)) {
+ if (open_page_at(pfd, pid, parent, flags)) {
if (errno != ENOENT)
goto err_free;
xfree(parent);
@@ -192,13 +192,13 @@ err_cl:
return -1;
}
-static int open_page_read_at(int dfd, int pid, struct page_read *pr)
+static int open_page_at(int dfd, int pid, struct page_read *pr, int flags)
{
pr->pe = NULL;
pr->fd = open_image_at(dfd, CR_FD_PAGEMAP, O_RSTR, (long)pid);
if (pr->fd < 0) {
- pr->fd_pg = open_image_at(dfd, CR_FD_PAGES_OLD, O_RSTR, pid);
+ pr->fd_pg = open_image_at(dfd, CR_FD_PAGES_OLD, flags, pid);
if (pr->fd_pg < 0)
return -1;
@@ -209,12 +209,12 @@ static int open_page_read_at(int dfd, int pid, struct page_read *pr)
} else {
static unsigned ids = 1;
- if (try_open_parent(dfd, pid, pr)) {
+ if (try_open_parent(dfd, pid, pr, flags)) {
close(pr->fd);
return -1;
}
- pr->fd_pg = open_pages_image_at(dfd, O_RSTR, pr->fd);
+ pr->fd_pg = open_pages_image_at(dfd, flags, pr->fd);
if (pr->fd_pg < 0) {
close_page_read(pr);
return -1;
@@ -234,7 +234,17 @@ static int open_page_read_at(int dfd, int pid, struct page_read *pr)
return 0;
}
+static int open_page_read_at(int dfd, int pid, struct page_read *pr)
+{
+ return open_page_at(dfd, pid, pr, O_RSTR);
+}
+
int open_page_read(int pid, struct page_read *pr)
{
return open_page_read_at(get_service_fd(IMG_FD_OFF), pid, pr);
}
+
+int open_page_rw(int pid, struct page_read *pr)
+{
+ return open_page_at(get_service_fd(IMG_FD_OFF), pid, pr, O_RDWR);
+}
--
1.7.9.5
More information about the CRIU
mailing list