[CRIU] [PATCH 4/9] page-read: New abstraction for restoring pages
Pavel Emelyanov
xemul at parallels.com
Thu Apr 11 09:50:26 EDT 2013
Now we have 2 forms of storing pages -- legacy pages.img and
new pagemap + pages image. We'll have one more (ovz) and the
pagemap + pages will be stacked (snapshot restore). Thus it's
handy to have this as an page-reader object.
Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
---
Makefile.crtools | 1 +
cr-restore.c | 64 +++++++++++-------------------
include/page-read.h | 16 ++++++++
page-read.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 148 insertions(+), 42 deletions(-)
create mode 100644 include/page-read.h
create mode 100644 page-read.c
diff --git a/Makefile.crtools b/Makefile.crtools
index e7997f5..4d81c36 100644
--- a/Makefile.crtools
+++ b/Makefile.crtools
@@ -44,6 +44,7 @@ obj-y += cr-exec.o
obj-y += file-lock.o
obj-y += page-pipe.o
obj-y += page-xfer.o
+obj-y += page-read.o
ifneq ($(MAKECMDGOALS),clean)
incdeps := y
diff --git a/cr-restore.c b/cr-restore.c
index 9f02f34..1d0e1bd 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -55,6 +55,7 @@
#include "tty.h"
#include "cpu.h"
#include "file-lock.h"
+#include "page-read.h"
#include "protobuf.h"
#include "protobuf/sa.pb-c.h"
@@ -267,55 +268,32 @@ static int map_private_vma(pid_t pid, struct vma_area *vma, void *tgt_addr,
static int restore_priv_vma_content(pid_t pid)
{
struct vma_area *vma;
- int fd, fd_pg, ret = 0;
+ int ret = 0;
unsigned int nr_restored = 0;
unsigned int nr_shared = 0;
unsigned int nr_droped = 0;
unsigned long va;
+ struct page_read pr;
vma = list_first_entry(&rst_vmas.h, struct vma_area, list);
-
- fd = open_image(CR_FD_PAGEMAP, O_RSTR, (long)pid);
- if (fd < 0) {
- fd_pg = open_image(CR_FD_PAGES_OLD, O_RSTR, pid);
- if (fd_pg < 0)
- return -1;
- } else {
- fd_pg = open_pages_image(O_RSTR, fd);
- if (fd_pg < 0) {
- close(fd);
- return -1;
- }
- }
+ ret = open_page_read(pid, &pr);
+ if (ret)
+ return -1;
/*
* Read page contents.
*/
while (1) {
unsigned long off, i, nr_pages;;
+ struct iovec iov;
- if (fd >= 0) {
- PagemapEntry *pe;
-
- ret = pb_read_one_eof(fd, &pe, PB_PAGEMAP);
- if (ret <= 0)
- break;
-
- va = (unsigned long)decode_pointer(pe->vaddr);
- nr_pages = pe->nr_pages;
-
- pagemap_entry__free_unpacked(pe, NULL);
- } else {
- __u64 img_va;
+ ret = pr.get_pagemap(&pr, &iov);
+ if (ret <= 0)
+ break;
- ret = read_img_eof(fd_pg, &img_va);
- if (ret <= 0)
- break;
-
- va = (unsigned long)decode_pointer(img_va);
- nr_pages = 1;
- }
+ va = (unsigned long)iov.iov_base;
+ nr_pages = iov.iov_len / PAGE_SIZE;
for (i = 0; i < nr_pages; i++) {
unsigned char buf[PAGE_SIZE];
@@ -345,17 +323,16 @@ static int restore_priv_vma_content(pid_t pid)
}
off = (va - vma->vma.start) / PAGE_SIZE;
- va += PAGE_SIZE;
set_bit(off, vma->page_bitmap);
if (vma->ppage_bitmap)
clear_bit(off, vma->ppage_bitmap);
- ret = read(fd_pg, buf, PAGE_SIZE);
- if (ret != PAGE_SIZE) {
- pr_err("Can'r read mapping page %d\n", ret);
- return -1;
- }
+ ret = pr.read_page(&pr, va, buf);
+ if (ret < 0)
+ break;
+
+ va += PAGE_SIZE;
p = decode_pointer((off) * PAGE_SIZE +
vma_premmaped_start(&vma->vma));
@@ -368,9 +345,12 @@ static int restore_priv_vma_content(pid_t pid)
memcpy(p, buf, PAGE_SIZE);
nr_restored++;
}
+
+ if (pr.put_pagemap)
+ pr.put_pagemap(&pr);
}
- close(fd_pg);
- close(fd);
+
+ pr.close(&pr);
if (ret < 0)
return ret;
diff --git a/include/page-read.h b/include/page-read.h
new file mode 100644
index 0000000..79b595a
--- /dev/null
+++ b/include/page-read.h
@@ -0,0 +1,16 @@
+#ifndef __CR_PAGE_READ_H__
+#define __CR_PAGE_READ_H__
+#include "protobuf/pagemap.pb-c.h"
+
+struct page_read {
+ int (*get_pagemap)(struct page_read *, struct iovec *iov);
+ int (*read_page)(struct page_read *, unsigned long vaddr, void *);
+ void (*put_pagemap)(struct page_read *);
+ void (*close)(struct page_read *);
+
+ int fd;
+ int fd_pg;
+};
+
+int open_page_read(int pid, struct page_read *);
+#endif
diff --git a/page-read.c b/page-read.c
new file mode 100644
index 0000000..8801892
--- /dev/null
+++ b/page-read.c
@@ -0,0 +1,109 @@
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "crtools.h"
+#include "page-read.h"
+
+#include "protobuf.h"
+#include "protobuf/pagemap.pb-c.h"
+
+static int get_page_vaddr(struct page_read *pr, struct iovec *iov)
+{
+ int ret;
+ __u64 img_va;
+
+ ret = read_img_eof(pr->fd_pg, &img_va);
+ if (ret <= 0)
+ return ret;
+
+ iov->iov_base = (void *)decode_pointer(img_va);
+ iov->iov_len = PAGE_SIZE;
+
+ return 1;
+}
+
+static int read_page(struct page_read *pr, unsigned long vaddr, void *buf)
+{
+ int ret;
+
+ ret = read(pr->fd_pg, buf, PAGE_SIZE);
+ if (ret != PAGE_SIZE) {
+ pr_err("Can'r read mapping page %d\n", ret);
+ return -1;
+ }
+
+ return 1;
+}
+
+static int get_pagemap(struct page_read *pr, struct iovec *iov)
+{
+ int ret;
+ PagemapEntry *pe;
+
+ ret = pb_read_one_eof(pr->fd, &pe, PB_PAGEMAP);
+ if (ret <= 0)
+ return ret;
+
+ iov->iov_base = decode_pointer(pe->vaddr);
+ iov->iov_len = pe->nr_pages * PAGE_SIZE;
+ pagemap_entry__free_unpacked(pe, NULL);
+
+ return 1;
+}
+
+static void put_pagemap(struct page_read *pr)
+{
+}
+
+static int read_pagemap_page(struct page_read *pr, unsigned long vaddr, void *buf)
+{
+ int ret;
+
+ ret = read(pr->fd_pg, buf, PAGE_SIZE);
+ if (ret != PAGE_SIZE) {
+ pr_err("Can'r read mapping page %d\n", ret);
+ return -1;
+ }
+
+ return 1;
+}
+
+static void close_page_read(struct page_read *pr)
+{
+ close(pr->fd_pg);
+ close(pr->fd);
+}
+
+static int open_page_read_at(int dfd, int pid, struct page_read *pr)
+{
+ 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);
+ if (pr->fd_pg < 0)
+ return -1;
+
+ pr->get_pagemap = get_page_vaddr;
+ pr->put_pagemap = NULL;
+ pr->read_page = read_page;
+ } else {
+ pr->fd_pg = open_pages_image_at(dfd, O_RSTR, pr->fd);
+ if (pr->fd_pg < 0) {
+ close_page_read(pr);
+ return -1;
+ }
+
+ pr->get_pagemap = get_pagemap;
+ pr->put_pagemap = put_pagemap;
+ pr->read_page = read_pagemap_page;
+ }
+
+ pr->close = close_page_read;
+
+ return 0;
+}
+
+int open_page_read(int pid, struct page_read *pr)
+{
+ return open_page_read_at(get_service_fd(IMG_FD_OFF), pid, pr);
+}
--
1.7.11.7
More information about the CRIU
mailing list