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
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
......
......@@ -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;
......
#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