[CRIU] [PATCH 2/3] mem: use batch mode for dumping anonymous memory
Pavel Emelyanov
xemul at parallels.com
Wed Jan 29 05:17:24 PST 2014
On 01/27/2014 06:22 PM, Andrey Vagin wrote:
> 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));
Plz, don't format text in "while I'm at it" mode.
> 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);
You've just ruined the MEMWRITE stats. Please, don't.
> - 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);
>
More information about the CRIU
mailing list