[CRIU] [PATCH 2/3] mem: use batch mode for dumping anonymous memory

Andrey Vagin avagin at openvz.org
Mon Jan 27 06:22:10 PST 2014


TODO: need to rework pre-dump, because currently dumping data from
      pipes are postponed. We are going to use sys_process_vm_readv for
      this.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 mem.c | 120 ++++++++++++++++++++++++++++++++++++++----------------------------
 1 file changed, 69 insertions(+), 51 deletions(-)

diff --git a/mem.c b/mem.c
index 4e21d20..ab287a5 100644
--- a/mem.c
+++ b/mem.c
@@ -183,6 +183,52 @@ static struct parasite_dump_pages_args *prep_dump_pages_args(struct parasite_ctl
 	return args;
 }
 
+struct pp_mem_batch_args
+{
+	struct parasite_ctl *ctl;
+	struct parasite_dump_pages_args *args;
+	struct page_xfer *xfer;
+};
+
+static int fill_pages(struct page_pipe *pp, void *_args)
+{
+	struct pp_mem_batch_args *pp_args = _args;
+	struct parasite_ctl *ctl = pp_args->ctl;
+	struct parasite_dump_pages_args *args = pp_args->args;
+	struct page_pipe_buf *ppb;
+	int ret = 0;
+
+	/* Step 2 -- grab pages into page-pipe */
+	list_for_each_entry(ppb, &pp->bufs, l) {
+		args->nr_segs = ppb->nr_segs;
+		args->nr_pages = ppb->pages_in;
+		pr_debug("PPB: %d pages %d segs %u pipe %d off\n",
+				args->nr_pages, args->nr_segs, ppb->pipe_size, args->off);
+
+		ret = __parasite_execute_daemon(PARASITE_CMD_DUMPPAGES, ctl);
+		if (ret < 0)
+			return -1;
+		ret = parasite_send_fd(ctl, ppb->p[1]);
+		if (ret)
+			return -1;
+
+		ret = __parasite_wait_daemon_ack(PARASITE_CMD_DUMPPAGES, ctl);
+		if (ret < 0)
+			return -1;
+
+		args->off += args->nr_segs;
+	}
+
+	/*
+	 * Step 3 -- write pages into image (or delay writing for
+	 *           pre-dump action (see pre_dump_one_task)
+	 */
+	if (pp_args->xfer)
+		ret = page_xfer_dump_pages(pp_args->xfer, pp, 0);
+
+	return ret;
+}
+
 static int __parasite_dump_pages_seized(struct parasite_ctl *ctl,
 		struct parasite_dump_pages_args *args,
 		struct vm_area_list *vma_area_list,
@@ -191,8 +237,9 @@ static int __parasite_dump_pages_seized(struct parasite_ctl *ctl,
 	u64 *map;
 	int pagemap;
 	struct page_pipe *pp;
-	struct page_pipe_buf *ppb;
 	struct vma_area *vma_area;
+	struct page_xfer xfer;
+	struct pp_mem_batch_args pp_args = {ctl, args, NULL};
 	int ret = -1;
 
 	pr_info("\n");
@@ -217,80 +264,51 @@ static int __parasite_dump_pages_seized(struct parasite_ctl *ctl,
 		goto out_free;
 
 	ret = -1;
-	pp = create_page_pipe(vma_area_list->priv_size / 2, pargs_iovs(args));
+	pp = create_page_pipe(vma_area_list->priv_size / 2,
+					pargs_iovs(args));
 	if (!pp)
 		goto out_close;
 
-	/*
-	 * Step 1 -- generate the pagemap
-	 */
+	if (pp_ret == NULL) {
+		ret = open_page_xfer(&xfer, CR_FD_PAGEMAP, ctl->pid.virt);
+		if (ret < 0)
+			goto out_pp;
 
+		pp_args.xfer = &xfer;
+		page_pipe_start_batching(pp, &fill_pages, &pp_args);
+	}
+
+	args->off = 0;
 	list_for_each_entry(vma_area, &vma_area_list->h, list) {
 		if (!privately_dump_vma(vma_area))
 			continue;
 
 		ret = generate_iovs(vma_area, pagemap, pp, map);
 		if (ret < 0)
-			goto out_pp;
+			goto out_xfer;
 	}
+	if (pp_ret)
+		ret = fill_pages(pp, &pp_args);
+	else
+		ret = page_pipe_complete_batch(pp);
+	if (ret)
+		goto out_xfer;
 
 	debug_show_page_pipe(pp);
 
-	/*
-	 * Step 2 -- grab pages into page-pipe
-	 */
-
-	args->off = 0;
-	list_for_each_entry(ppb, &pp->bufs, l) {
-		args->nr_segs = ppb->nr_segs;
-		args->nr_pages = ppb->pages_in;
-		pr_debug("PPB: %d pages %d segs %u pipe %d off\n",
-				args->nr_pages, args->nr_segs, ppb->pipe_size, args->off);
-
-		ret = __parasite_execute_daemon(PARASITE_CMD_DUMPPAGES, ctl);
-		if (ret < 0)
-			goto out_pp;
-		ret = parasite_send_fd(ctl, ppb->p[1]);
-		if (ret)
-			goto out_pp;
-
-		ret = __parasite_wait_daemon_ack(PARASITE_CMD_DUMPPAGES, ctl);
-		if (ret < 0)
-			goto out_pp;
-
-		args->off += args->nr_segs;
-	}
-
 	timing_stop(TIME_MEMDUMP);
 
-	/*
-	 * Step 3 -- write pages into image (or delay writing for
-	 *           pre-dump action (see pre_dump_one_task)
-	 */
-
 	if (pp_ret)
 		*pp_ret = pp;
-	else {
-		struct page_xfer xfer;
-
-		timing_start(TIME_MEMWRITE);
-		ret = open_page_xfer(&xfer, CR_FD_PAGEMAP, ctl->pid.virt);
-		if (ret < 0)
-			goto out_pp;
-
-		ret = page_xfer_dump_pages(&xfer, pp, 0);
-		if (ret < 0)
-			goto out_pp;
-
-		xfer.close(&xfer);
-		timing_stop(TIME_MEMWRITE);
-	}
 
 	/*
 	 * Step 4 -- clean up
 	 */
 
 	ret = task_reset_dirty_track(ctl->pid.real);
+out_xfer:
+	if (pp_ret == NULL)
+		xfer.close(&xfer);
 out_pp:
 	if (ret || !pp_ret)
 		destroy_page_pipe(pp);
-- 
1.8.3.1



More information about the CRIU mailing list