[CRIU] [PATCH 07/12]v2 deduplication: look up for old pages in previous snapshot

Tikhomirov Pavel snorcht at gmail.com
Mon Dec 16 02:55:31 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          |  128 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/page-read.h |    3 ++
 page-read.c         |   24 +++++++---
 3 files changed, 148 insertions(+), 7 deletions(-)

diff --git a/cr-dedup.c b/cr-dedup.c
index 225ab2d..2a9cbf5 100644
--- a/cr-dedup.c
+++ b/cr-dedup.c
@@ -1,8 +1,136 @@
 #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;
+	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 off_real;
+	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, 1);
+		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;
 }
diff --git a/include/page-read.h b/include/page-read.h
index a12cbee..23cb4fa 100644
--- a/include/page-read.h
+++ b/include/page-read.h
@@ -67,6 +67,9 @@ struct page_read {
 };
 
 extern int open_page_read(int pid, struct page_read *);
+extern int open_page_rw(int pid, struct page_read *);
 extern inline void pagemap2iovec(PagemapEntry *pe, struct iovec *iov);
 extern int seek_pagemap_page(struct page_read *pr, unsigned long vaddr, int flags);
+
+extern int dedup_one_iovec(struct page_read *pr, struct iovec *iov);
 #endif /* __CR_PAGE_READ_H__ */
diff --git a/page-read.c b/page-read.c
index 01a387e..e7e2037 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