diff --git a/Makefile.crtools b/Makefile.crtools index 4a0ce0d76..62015c46a 100644 --- a/Makefile.crtools +++ b/Makefile.crtools @@ -41,6 +41,7 @@ obj-y += tty.o obj-y += cr-exec.o obj-y += file-lock.o obj-y += page-pipe.o +obj-y += page-xfer.o ifneq ($(MAKECMDGOALS),clean) incdeps := y diff --git a/include/page-xfer.h b/include/page-xfer.h new file mode 100644 index 000000000..1a807af76 --- /dev/null +++ b/include/page-xfer.h @@ -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 diff --git a/page-xfer.c b/page-xfer.c new file mode 100644 index 000000000..bbf769269 --- /dev/null +++ b/page-xfer.c @@ -0,0 +1,48 @@ +#include + +#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; +} diff --git a/parasite-syscall.c b/parasite-syscall.c index cae495fcd..ad778ba15 100644 --- a/parasite-syscall.c +++ b/parasite-syscall.c @@ -23,6 +23,7 @@ #include "pstree.h" #include "net.h" #include "page-pipe.h" +#include "page-xfer.h" #include #include @@ -549,11 +550,12 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl, int vpid, { struct parasite_dump_pages_args *args; u64 *map; - int pagemap, fd, fd_pg; + int pagemap; struct page_pipe *pp; struct page_pipe_buf *ppb; struct vma_area *vma_area; int ret = -1; + struct page_xfer xfer; pr_info("\n"); 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; } - fd = open_image(CR_FD_PAGEMAP, O_DUMP, (long)vpid); - if (fd < 0) + ret = open_page_xfer(&xfer, CR_FD_PAGEMAP, vpid); + if (ret < 0) goto out_pp; - fd_pg = open_pages_image(O_DUMP, fd); - if (fd_pg < 0) - goto out_fd; ret = -1; 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); for (i = 0; i < ppb->nr_segs; i++) { - PagemapEntry pe = PAGEMAP_ENTRY__INIT; 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, (unsigned int)(iov->iov_len / PAGE_SIZE)); - if (pb_write_one(fd, &pe, PB_PAGEMAP) < 0) - break; - if (splice(ppb->p[0], NULL, fd_pg, NULL, iov->iov_len, - SPLICE_F_MOVE) != iov->iov_len) - break; + if (xfer.write_pagemap(&xfer, iov, ppb->p[0])) + goto out_xfer; } - - if (i != ppb->nr_segs) - goto out_fds; } + ret = 0; -out_fds: - close(fd_pg); -out_fd: - close(fd); +out_xfer: + xfer.close(&xfer); out_pp: destroy_page_pipe(pp); out_close: