diff --git a/criu/cr-dump.c b/criu/cr-dump.c index 0e297acb7..cf0ac8093 100644 --- a/criu/cr-dump.c +++ b/criu/cr-dump.c @@ -1491,7 +1491,7 @@ static int cr_pre_dump_finish(int ret) goto err; mem_pp = dmpi(item)->mem_pp; - ret = page_xfer_dump_pages(&xfer, mem_pp, 0, true); + ret = page_xfer_dump_pages(&xfer, mem_pp, true); xfer.close(&xfer); diff --git a/criu/include/page-xfer.h b/criu/include/page-xfer.h index 2b806c797..00b18d3b4 100644 --- a/criu/include/page-xfer.h +++ b/criu/include/page-xfer.h @@ -17,6 +17,12 @@ struct page_xfer { int (*write_pages)(struct page_xfer *self, int pipe, unsigned long len); void (*close)(struct page_xfer *self); + /* + * In case we need to dump pagemaps not as-is, but + * relative to some address. Used, e.g. by shmem. + */ + unsigned long offset; + /* private data for every page-xfer engine */ union { struct /* local */ { @@ -35,8 +41,7 @@ struct page_xfer { extern int open_page_xfer(struct page_xfer *xfer, int fd_type, long id); struct page_pipe; -extern int page_xfer_dump_pages(struct page_xfer *, struct page_pipe *, - unsigned long off, bool dump_lazy); +extern int page_xfer_dump_pages(struct page_xfer *, struct page_pipe *, bool dump_lazy); extern int connect_to_page_server_to_send(void); extern int connect_to_page_server_to_recv(int epfd); extern int disconnect_from_page_server(void); diff --git a/criu/mem.c b/criu/mem.c index dbeffe12b..599c3036e 100644 --- a/criu/mem.c +++ b/criu/mem.c @@ -284,7 +284,7 @@ static int xfer_pages(struct page_pipe *pp, struct page_xfer *xfer, bool lazy) * pre-dump action (see pre_dump_one_task) */ timing_start(TIME_MEMWRITE); - ret = page_xfer_dump_pages(xfer, pp, 0, !lazy); + ret = page_xfer_dump_pages(xfer, pp, !lazy); timing_stop(TIME_MEMWRITE); return ret; diff --git a/criu/page-xfer.c b/criu/page-xfer.c index 5d4bf1128..737e05fa3 100644 --- a/criu/page-xfer.c +++ b/criu/page-xfer.c @@ -378,6 +378,8 @@ out: int open_page_xfer(struct page_xfer *xfer, int fd_type, long id) { + xfer->offset = 0; + if (opts.use_page_server) return open_page_server_xfer(xfer, fd_type, id); else @@ -385,10 +387,10 @@ int open_page_xfer(struct page_xfer *xfer, int fd_type, long id) } static int page_xfer_dump_hole(struct page_xfer *xfer, - struct iovec *hole, unsigned long off, u32 flags) + struct iovec *hole, u32 flags) { - BUG_ON(hole->iov_base < (void *)off); - hole->iov_base -= off; + BUG_ON(hole->iov_base < (void *)xfer->offset); + hole->iov_base -= xfer->offset; pr_debug("\th %p [%u]\n", hole->iov_base, (unsigned int)(hole->iov_len / PAGE_SIZE)); @@ -411,7 +413,7 @@ static int get_hole_flags(struct page_pipe *pp, int n) } static int dump_holes(struct page_xfer *xfer, struct page_pipe *pp, - unsigned int *cur_hole, void *limit, unsigned long off) + unsigned int *cur_hole, void *limit) { int ret; @@ -423,7 +425,7 @@ static int dump_holes(struct page_xfer *xfer, struct page_pipe *pp, break; hole_flags = get_hole_flags(pp, *cur_hole); - ret = page_xfer_dump_hole(xfer, &hole, off, hole_flags); + ret = page_xfer_dump_hole(xfer, &hole, hole_flags); if (ret) return ret; } @@ -432,7 +434,7 @@ static int dump_holes(struct page_xfer *xfer, struct page_pipe *pp, } int page_xfer_dump_pages(struct page_xfer *xfer, struct page_pipe *pp, - unsigned long off, bool dump_lazy) + bool dump_lazy) { struct page_pipe_buf *ppb; unsigned int cur_hole = 0; @@ -449,12 +451,12 @@ int page_xfer_dump_pages(struct page_xfer *xfer, struct page_pipe *pp, struct iovec iov = ppb->iov[i]; u32 flags = PE_PRESENT; - ret = dump_holes(xfer, pp, &cur_hole, iov.iov_base, off); + ret = dump_holes(xfer, pp, &cur_hole, iov.iov_base); if (ret) return ret; - BUG_ON(iov.iov_base < (void *)off); - iov.iov_base -= off; + BUG_ON(iov.iov_base < (void *)xfer->offset); + iov.iov_base -= xfer->offset; pr_debug("\tp %p [%u]\n", iov.iov_base, (unsigned int)(iov.iov_len / PAGE_SIZE)); @@ -475,7 +477,7 @@ int page_xfer_dump_pages(struct page_xfer *xfer, struct page_pipe *pp, } } - return dump_holes(xfer, pp, &cur_hole, NULL, off); + return dump_holes(xfer, pp, &cur_hole, NULL); } /* diff --git a/criu/shmem.c b/criu/shmem.c index cc5157d6b..7ab396359 100644 --- a/criu/shmem.c +++ b/criu/shmem.c @@ -628,7 +628,7 @@ int add_shmem_area(pid_t pid, VmaEntry *vma, u64 *map) return 0; } -static int dump_pages(struct page_pipe *pp, struct page_xfer *xfer, void *addr) +static int dump_pages(struct page_pipe *pp, struct page_xfer *xfer) { struct page_pipe_buf *ppb; @@ -640,7 +640,7 @@ static int dump_pages(struct page_pipe *pp, struct page_xfer *xfer, void *addr) return -1; } - return page_xfer_dump_pages(xfer, pp, (unsigned long)addr, true); + return page_xfer_dump_pages(xfer, pp, true); } static int next_data_segment(int fd, unsigned long pfn, @@ -687,6 +687,8 @@ static int do_dump_one_shmem(int fd, void *addr, struct shmem_info *si) if (err) goto err_pp; + xfer.offset = (unsigned long)addr; + for (pfn = 0; pfn < nrpages; pfn++) { unsigned int pgstate = PST_DIRTY; bool use_mc = true; @@ -718,7 +720,7 @@ again: ret = page_pipe_add_page(pp, pgaddr, 0); if (ret == -EAGAIN) { - ret = dump_pages(pp, &xfer, addr); + ret = dump_pages(pp, &xfer); if (ret) goto err_xfer; page_pipe_reinit(pp); @@ -727,7 +729,7 @@ again: goto err_xfer; } - ret = dump_pages(pp, &xfer, addr); + ret = dump_pages(pp, &xfer); err_xfer: xfer.close(&xfer);