[CRIU] [PATCH 1/1] page-read: Teach page-read to read multiple pages at once
Pavel Emelyanov
xemul at parallels.com
Mon Nov 9 04:44:58 PST 2015
This is preparatory patch, the problem to solve is described in
the next one.
Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
---
cr-restore.c | 4 ++--
include/page-read.h | 2 +-
page-read.c | 35 +++++++++++++++++++++++++----------
3 files changed, 28 insertions(+), 13 deletions(-)
diff --git a/cr-restore.c b/cr-restore.c
index a33273c..8770f57 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -465,7 +465,7 @@ static int restore_priv_vma_content(void)
if (vma->ppage_bitmap) { /* inherited vma */
clear_bit(off, vma->ppage_bitmap);
- ret = pr.read_page(&pr, va, buf);
+ ret = pr.read_pages(&pr, va, 1, buf);
if (ret < 0)
goto err_read;
va += PAGE_SIZE;
@@ -479,7 +479,7 @@ static int restore_priv_vma_content(void)
memcpy(p, buf, PAGE_SIZE);
} else {
- ret = pr.read_page(&pr, va, p);
+ ret = pr.read_pages(&pr, va, 1, p);
if (ret < 0)
goto err_read;
va += PAGE_SIZE;
diff --git a/include/page-read.h b/include/page-read.h
index 9e3013a..827e4ac 100644
--- a/include/page-read.h
+++ b/include/page-read.h
@@ -47,7 +47,7 @@ struct page_read {
*/
int (*get_pagemap)(struct page_read *, struct iovec *iov);
/* reads page from current pagemap */
- int (*read_page)(struct page_read *, unsigned long vaddr, void *);
+ int (*read_pages)(struct page_read *, unsigned long vaddr, int nr, void *);
/* stop working on current pagemap */
void (*put_pagemap)(struct page_read *);
void (*close)(struct page_read *);
diff --git a/page-read.c b/page-read.c
index 832c057..1ee7544 100644
--- a/page-read.c
+++ b/page-read.c
@@ -30,10 +30,12 @@ static int get_page_vaddr(struct page_read *pr, struct iovec *iov)
return 1;
}
-static int read_page(struct page_read *pr, unsigned long vaddr, void *buf)
+static int read_page(struct page_read *pr, unsigned long vaddr, int nr, void *buf)
{
int ret;
+ BUG_ON(nr != 1);
+
ret = read(img_raw_fd(pr->pmi), buf, PAGE_SIZE);
if (ret != PAGE_SIZE) {
pr_err("Can't read mapping page %d\n", ret);
@@ -82,7 +84,7 @@ static void put_pagemap(struct page_read *pr)
pagemap_entry__free_unpacked(pr->pe, NULL);
}
-static int read_pagemap_page(struct page_read *pr, unsigned long vaddr, void *buf);
+static int read_pagemap_page(struct page_read *pr, unsigned long vaddr, int nr, void *buf);
static void skip_pagemap_pages(struct page_read *pr, unsigned long len)
{
@@ -132,38 +134,51 @@ new_pagemap:
}
}
-static int read_pagemap_page(struct page_read *pr, unsigned long vaddr, void *buf)
+static inline void pagemap_bound_check(PagemapEntry *pe, unsigned long vaddr, int nr)
+{
+ if (vaddr < pe->vaddr || (vaddr - pe->vaddr) / PAGE_SIZE + nr > pe->nr_pages) {
+ pr_err("Page read err %lx:%u vs %lx:%u\n",
+ pe->vaddr, pe->nr_pages, vaddr, nr);
+ BUG();
+ }
+}
+
+static int read_pagemap_page(struct page_read *pr, unsigned long vaddr, int nr, void *buf)
{
int ret;
+ unsigned long len = nr * PAGE_SIZE;
+
+ pagemap_bound_check(pr->pe, vaddr, nr);
if (pr->pe->in_parent) {
pr_debug("\tpr%u Read page %lx from parent\n", pr->id, vaddr);
ret = seek_pagemap_page(pr->parent, vaddr, true);
if (ret <= 0)
return -1;
- ret = read_pagemap_page(pr->parent, vaddr, buf);
+ ret = read_pagemap_page(pr->parent, vaddr, nr, buf);
if (ret == -1)
return ret;
} else {
int fd = img_raw_fd(pr->pi);
off_t current_vaddr = lseek(fd, 0, SEEK_CUR);
+
pr_debug("\tpr%u Read page %lx from self %lx/%"PRIx64"\n", pr->id,
vaddr, pr->cvaddr, current_vaddr);
- ret = read(fd, buf, PAGE_SIZE);
- if (ret != PAGE_SIZE) {
+ ret = read(fd, buf, len);
+ if (ret != len) {
pr_perror("Can't read mapping page %d", ret);
return -1;
}
if (opts.auto_dedup) {
- ret = punch_hole(pr, current_vaddr, (unsigned int)PAGE_SIZE, false);
+ ret = punch_hole(pr, current_vaddr, len, false);
if (ret == -1) {
return -1;
}
}
}
- pr->cvaddr += PAGE_SIZE;
+ pr->cvaddr += len;
return 1;
}
@@ -277,7 +292,7 @@ int open_page_read_at(int dfd, int pid, struct page_read *pr, int pr_flags)
pr->get_pagemap = get_pagemap;
pr->put_pagemap = put_pagemap;
- pr->read_page = read_pagemap_page;
+ pr->read_pages = read_pagemap_page;
pr->close = close_page_read;
pr->id = ids++;
@@ -298,7 +313,7 @@ open_old:
pr->get_pagemap = get_page_vaddr;
pr->put_pagemap = NULL;
- pr->read_page = read_page;
+ pr->read_pages = read_page;
pr->pi = NULL;
pr->close = close_page_read;
--
1.9.3
More information about the CRIU
mailing list