[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