mirror of
https://github.com/checkpoint-restore/criu
synced 2025-09-01 14:55:39 +00:00
mem: Abstraction layer for putting pages into image
We'll send them over network soon, so prepare abstraction layer for this. Shmem is not on this scheme yet. Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
@@ -41,6 +41,7 @@ obj-y += tty.o
|
|||||||
obj-y += cr-exec.o
|
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
|
||||||
|
|
||||||
ifneq ($(MAKECMDGOALS),clean)
|
ifneq ($(MAKECMDGOALS),clean)
|
||||||
incdeps := y
|
incdeps := y
|
||||||
|
13
include/page-xfer.h
Normal file
13
include/page-xfer.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#ifndef __CR_PAGE_XFER__H__
|
||||||
|
#define __CR_PAGE_XFER__H__
|
||||||
|
struct page_xfer {
|
||||||
|
int (*write_pagemap)(struct page_xfer *self, struct iovec *iov, int pipe);
|
||||||
|
void (*close)(struct page_xfer *self);
|
||||||
|
int fd;
|
||||||
|
union {
|
||||||
|
int fd_pg;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
int open_page_xfer(struct page_xfer *xfer, int fd_type, long id);
|
||||||
|
#endif
|
48
page-xfer.c
Normal file
48
page-xfer.c
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "crtools.h"
|
||||||
|
#include "page-xfer.h"
|
||||||
|
|
||||||
|
#include "protobuf.h"
|
||||||
|
#include "protobuf/pagemap.pb-c.h"
|
||||||
|
|
||||||
|
static int write_pagemap_loc(struct page_xfer *xfer,
|
||||||
|
struct iovec *iov, int p)
|
||||||
|
{
|
||||||
|
PagemapEntry pe = PAGEMAP_ENTRY__INIT;
|
||||||
|
|
||||||
|
pe.vaddr = encode_pointer(iov->iov_base);
|
||||||
|
pe.nr_pages = iov->iov_len / PAGE_SIZE;
|
||||||
|
|
||||||
|
if (pb_write_one(xfer->fd, &pe, PB_PAGEMAP) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (splice(p, NULL, xfer->fd_pg, NULL, iov->iov_len,
|
||||||
|
SPLICE_F_MOVE) != iov->iov_len)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void close_page_xfer(struct page_xfer *xfer)
|
||||||
|
{
|
||||||
|
close(xfer->fd_pg);
|
||||||
|
close(xfer->fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int open_page_xfer(struct page_xfer *xfer, int fd_type, long id)
|
||||||
|
{
|
||||||
|
xfer->fd = open_image(fd_type, O_DUMP, id);
|
||||||
|
if (xfer->fd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
xfer->fd_pg = open_pages_image(O_DUMP, xfer->fd);
|
||||||
|
if (xfer->fd_pg < 0) {
|
||||||
|
close(xfer->fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
xfer->write_pagemap = write_pagemap_loc;
|
||||||
|
xfer->close = close_page_xfer;
|
||||||
|
return 0;
|
||||||
|
}
|
@@ -23,6 +23,7 @@
|
|||||||
#include "pstree.h"
|
#include "pstree.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "page-pipe.h"
|
#include "page-pipe.h"
|
||||||
|
#include "page-xfer.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -549,11 +550,12 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl, int vpid,
|
|||||||
{
|
{
|
||||||
struct parasite_dump_pages_args *args;
|
struct parasite_dump_pages_args *args;
|
||||||
u64 *map;
|
u64 *map;
|
||||||
int pagemap, fd, fd_pg;
|
int pagemap;
|
||||||
struct page_pipe *pp;
|
struct page_pipe *pp;
|
||||||
struct page_pipe_buf *ppb;
|
struct page_pipe_buf *ppb;
|
||||||
struct vma_area *vma_area;
|
struct vma_area *vma_area;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
struct page_xfer xfer;
|
||||||
|
|
||||||
pr_info("\n");
|
pr_info("\n");
|
||||||
pr_info("Dumping pages (type: %d pid: %d)\n", CR_FD_PAGES, ctl->pid);
|
pr_info("Dumping pages (type: %d pid: %d)\n", CR_FD_PAGES, ctl->pid);
|
||||||
@@ -604,12 +606,9 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl, int vpid,
|
|||||||
args->off += args->nr;
|
args->off += args->nr;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = open_image(CR_FD_PAGEMAP, O_DUMP, (long)vpid);
|
ret = open_page_xfer(&xfer, CR_FD_PAGEMAP, vpid);
|
||||||
if (fd < 0)
|
if (ret < 0)
|
||||||
goto out_pp;
|
goto out_pp;
|
||||||
fd_pg = open_pages_image(O_DUMP, fd);
|
|
||||||
if (fd_pg < 0)
|
|
||||||
goto out_fd;
|
|
||||||
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
list_for_each_entry(ppb, &pp->bufs, l) {
|
list_for_each_entry(ppb, &pp->bufs, l) {
|
||||||
@@ -618,30 +617,19 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl, int vpid,
|
|||||||
pr_debug("Dump pages %d/%d\n", ppb->pages_in, ppb->nr_segs);
|
pr_debug("Dump pages %d/%d\n", ppb->pages_in, ppb->nr_segs);
|
||||||
|
|
||||||
for (i = 0; i < ppb->nr_segs; i++) {
|
for (i = 0; i < ppb->nr_segs; i++) {
|
||||||
PagemapEntry pe = PAGEMAP_ENTRY__INIT;
|
|
||||||
struct iovec *iov = &ppb->iov[i];
|
struct iovec *iov = &ppb->iov[i];
|
||||||
|
|
||||||
pe.vaddr = encode_pointer(iov->iov_base);
|
|
||||||
pe.nr_pages = iov->iov_len / PAGE_SIZE;
|
|
||||||
|
|
||||||
pr_debug("\t%p [%u]\n", iov->iov_base,
|
pr_debug("\t%p [%u]\n", iov->iov_base,
|
||||||
(unsigned int)(iov->iov_len / PAGE_SIZE));
|
(unsigned int)(iov->iov_len / PAGE_SIZE));
|
||||||
|
|
||||||
if (pb_write_one(fd, &pe, PB_PAGEMAP) < 0)
|
if (xfer.write_pagemap(&xfer, iov, ppb->p[0]))
|
||||||
break;
|
goto out_xfer;
|
||||||
if (splice(ppb->p[0], NULL, fd_pg, NULL, iov->iov_len,
|
}
|
||||||
SPLICE_F_MOVE) != iov->iov_len)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i != ppb->nr_segs)
|
|
||||||
goto out_fds;
|
|
||||||
}
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
out_fds:
|
out_xfer:
|
||||||
close(fd_pg);
|
xfer.close(&xfer);
|
||||||
out_fd:
|
|
||||||
close(fd);
|
|
||||||
out_pp:
|
out_pp:
|
||||||
destroy_page_pipe(pp);
|
destroy_page_pipe(pp);
|
||||||
out_close:
|
out_close:
|
||||||
|
Reference in New Issue
Block a user