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

Kir Kolyshkin kir at parallels.com
Mon Dec 16 10:08:39 PST 2013


On 12/16/2013 02:55 AM, Tikhomirov Pavel wrote:
> 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);

If you want errno, better use pr_perror() instead (and please note 
pr_perror adds \n itself).

> +		ret = -1;
> +		goto err;
> +	}
> +
> +	while (1) {
> +		errno = 0;
> +		ent = readdir(dirp);
> +		if (ent == NULL) {
> +			if (errno) {
> +				pr_err("Failed readdir, error=%d\n", errno);

ditto

> +				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;

Remember that you have

int main() {
...
     return cr_dedup();

elsewhere and you are not supposed to return negative values from
main(), so please either make cr_dedup() return positive non-zero
values in case of error (1 is the best candidate) or otherwise fix main().

> +
> +	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);
> +}



More information about the CRIU mailing list