Commit 757f9c57 authored by Pavel Emelyanov's avatar Pavel Emelyanov

page-read: New abstraction for restoring pages

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: 's avatarPavel Emelyanov <xemul@parallels.com>
parent eb5a3788
...@@ -44,6 +44,7 @@ obj-y += cr-exec.o ...@@ -44,6 +44,7 @@ obj-y += cr-exec.o
obj-y += file-lock.o obj-y += file-lock.o
obj-y += page-pipe.o obj-y += page-pipe.o
obj-y += page-xfer.o obj-y += page-xfer.o
obj-y += page-read.o
ifneq ($(MAKECMDGOALS),clean) ifneq ($(MAKECMDGOALS),clean)
incdeps := y incdeps := y
......
...@@ -55,6 +55,7 @@ ...@@ -55,6 +55,7 @@
#include "tty.h" #include "tty.h"
#include "cpu.h" #include "cpu.h"
#include "file-lock.h" #include "file-lock.h"
#include "page-read.h"
#include "protobuf.h" #include "protobuf.h"
#include "protobuf/sa.pb-c.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, ...@@ -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) static int restore_priv_vma_content(pid_t pid)
{ {
struct vma_area *vma; struct vma_area *vma;
int fd, fd_pg, ret = 0; int ret = 0;
unsigned int nr_restored = 0; unsigned int nr_restored = 0;
unsigned int nr_shared = 0; unsigned int nr_shared = 0;
unsigned int nr_droped = 0; unsigned int nr_droped = 0;
unsigned long va; unsigned long va;
struct page_read pr;
vma = list_first_entry(&rst_vmas.h, struct vma_area, list); vma = list_first_entry(&rst_vmas.h, struct vma_area, list);
ret = open_page_read(pid, &pr);
fd = open_image(CR_FD_PAGEMAP, O_RSTR, (long)pid); if (ret)
if (fd < 0) { return -1;
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;
}
}
/* /*
* Read page contents. * Read page contents.
*/ */
while (1) { while (1) {
unsigned long off, i, nr_pages;; unsigned long off, i, nr_pages;;
struct iovec iov;
if (fd >= 0) { ret = pr.get_pagemap(&pr, &iov);
PagemapEntry *pe; if (ret <= 0)
break;
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 = read_img_eof(fd_pg, &img_va); va = (unsigned long)iov.iov_base;
if (ret <= 0) nr_pages = iov.iov_len / PAGE_SIZE;
break;
va = (unsigned long)decode_pointer(img_va);
nr_pages = 1;
}
for (i = 0; i < nr_pages; i++) { for (i = 0; i < nr_pages; i++) {
unsigned char buf[PAGE_SIZE]; unsigned char buf[PAGE_SIZE];
...@@ -345,17 +323,16 @@ static int restore_priv_vma_content(pid_t pid) ...@@ -345,17 +323,16 @@ static int restore_priv_vma_content(pid_t pid)
} }
off = (va - vma->vma.start) / PAGE_SIZE; off = (va - vma->vma.start) / PAGE_SIZE;
va += PAGE_SIZE;
set_bit(off, vma->page_bitmap); set_bit(off, vma->page_bitmap);
if (vma->ppage_bitmap) if (vma->ppage_bitmap)
clear_bit(off, vma->ppage_bitmap); clear_bit(off, vma->ppage_bitmap);
ret = read(fd_pg, buf, PAGE_SIZE); ret = pr.read_page(&pr, va, buf);
if (ret != PAGE_SIZE) { if (ret < 0)
pr_err("Can'r read mapping page %d\n", ret); break;
return -1;
} va += PAGE_SIZE;
p = decode_pointer((off) * PAGE_SIZE + p = decode_pointer((off) * PAGE_SIZE +
vma_premmaped_start(&vma->vma)); vma_premmaped_start(&vma->vma));
...@@ -368,9 +345,12 @@ static int restore_priv_vma_content(pid_t pid) ...@@ -368,9 +345,12 @@ static int restore_priv_vma_content(pid_t pid)
memcpy(p, buf, PAGE_SIZE); memcpy(p, buf, PAGE_SIZE);
nr_restored++; nr_restored++;
} }
if (pr.put_pagemap)
pr.put_pagemap(&pr);
} }
close(fd_pg);
close(fd); pr.close(&pr);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
#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
#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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment