[CRIU] [PATCH v5 2/8] criu: slightly refactor memory dump to support delaying it

Andrew Vagin avagin at virtuozzo.com
Sun Jul 10 09:45:51 PDT 2016


Mike, pls take a look at this issue:
https://github.com/xemul/criu/issues/189

I think zombies are handled incorrectly here

On Wed, Jun 29, 2016 at 08:55:07AM +0300, Mike Rapoport wrote:
> * keep pointer to parasite_ctl in dmp_info to simplify pre_dump_finish
> and make pre_dump and dump interfaces the same
> * pass boolean rather than pp_ret pointer to parasite_dump_pages_seized to
> distinguish delayed and immediate dump more explicitly
> 
> Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
> ---
>  criu/cr-dump.c                  | 23 +++++++++++------------
>  criu/include/mem.h              |  2 +-
>  criu/include/parasite-syscall.h |  1 -
>  criu/include/pstree.h           |  2 ++
>  criu/mem.c                      | 33 ++++++++++++++++-----------------
>  criu/parasite-syscall.c         |  2 ++
>  6 files changed, 32 insertions(+), 31 deletions(-)
> 
> diff --git a/criu/cr-dump.c b/criu/cr-dump.c
> index 00d28e9..33355fb 100644
> --- a/criu/cr-dump.c
> +++ b/criu/cr-dump.c
> @@ -1086,7 +1086,7 @@ err:
>  	return ret;
>  }
>  
> -static int pre_dump_one_task(struct pstree_item *item, struct list_head *ctls)
> +static int pre_dump_one_task(struct pstree_item *item)
>  {
>  	pid_t pid = item->pid.real;
>  	struct vm_area_list vmas;
> @@ -1142,13 +1142,12 @@ static int pre_dump_one_task(struct pstree_item *item, struct list_head *ctls)
>  
>  	parasite_ctl->pid.virt = item->pid.virt = misc.pid;
>  
> -	ret = parasite_dump_pages_seized(parasite_ctl, &vmas, &parasite_ctl->mem_pp);
> +	ret = parasite_dump_pages_seized(parasite_ctl, &vmas, true);
>  	if (ret)
>  		goto err_cure;
>  
>  	if (parasite_cure_remote(parasite_ctl))
>  		pr_err("Can't cure (pid: %d) from parasite\n", pid);
> -	list_add_tail(&parasite_ctl->pre_list, ctls);
>  err_free:
>  	free_mappings(&vmas);
>  err:
> @@ -1299,7 +1298,7 @@ static int dump_one_task(struct pstree_item *item)
>  		}
>  	}
>  
> -	ret = parasite_dump_pages_seized(parasite_ctl, &vmas, NULL);
> +	ret = parasite_dump_pages_seized(parasite_ctl, &vmas, false);
>  	if (ret)
>  		goto err_cure;
>  
> @@ -1408,12 +1407,11 @@ static int setup_alarm_handler()
>  	return 0;
>  }
>  
> -static int cr_pre_dump_finish(struct list_head *ctls, int ret)
> +static int cr_pre_dump_finish(int ret)
>  {
> -	struct parasite_ctl *ctl, *n;
> +	struct pstree_item *item;
>  
>  	pstree_switch_state(root_item, TASK_ALIVE);
> -	free_pstree(root_item);
>  
>  	timing_stop(TIME_FROZEN);
>  
> @@ -1421,7 +1419,8 @@ static int cr_pre_dump_finish(struct list_head *ctls, int ret)
>  		goto err;
>  
>  	pr_info("Pre-dumping tasks' memory\n");
> -	list_for_each_entry_safe(ctl, n, ctls, pre_list) {
> +	for_each_pstree_item(item) {
> +		struct parasite_ctl *ctl = dmpi(item)->parasite_ctl;
>  		struct page_xfer xfer;
>  
>  		pr_info("\tPre-dumping %d\n", ctl->pid.virt);
> @@ -1440,10 +1439,11 @@ static int cr_pre_dump_finish(struct list_head *ctls, int ret)
>  		timing_stop(TIME_MEMWRITE);
>  
>  		destroy_page_pipe(ctl->mem_pp);
> -		list_del(&ctl->pre_list);
>  		parasite_cure_local(ctl);
>  	}
>  
> +	free_pstree(root_item);
> +
>  	if (irmap_predump_run()) {
>  		ret = -1;
>  		goto err;
> @@ -1469,7 +1469,6 @@ int cr_pre_dump_tasks(pid_t pid)
>  {
>  	struct pstree_item *item;
>  	int ret = -1;
> -	LIST_HEAD(ctls);
>  
>  	root_item = alloc_pstree_item();
>  	if (!root_item)
> @@ -1520,7 +1519,7 @@ int cr_pre_dump_tasks(pid_t pid)
>  		goto err;
>  
>  	for_each_pstree_item(item)
> -		if (pre_dump_one_task(item, &ctls))
> +		if (pre_dump_one_task(item))
>  			goto err;
>  
>  	if (irmap_predump_prep())
> @@ -1528,7 +1527,7 @@ int cr_pre_dump_tasks(pid_t pid)
>  
>  	ret = 0;
>  err:
> -	return cr_pre_dump_finish(&ctls, ret);
> +	return cr_pre_dump_finish(ret);
>  }
>  
>  static int cr_dump_finish(int ret)
> diff --git a/criu/include/mem.h b/criu/include/mem.h
> index 9377bbc..a9750db 100644
> --- a/criu/include/mem.h
> +++ b/criu/include/mem.h
> @@ -11,7 +11,7 @@ extern int do_task_reset_dirty_track(int pid);
>  extern unsigned int dump_pages_args_size(struct vm_area_list *vmas);
>  extern int parasite_dump_pages_seized(struct parasite_ctl *ctl,
>  				      struct vm_area_list *vma_area_list,
> -				      struct page_pipe **pp);
> +				      bool delayed_dump);
>  
>  #define PME_PRESENT		(1ULL << 63)
>  #define PME_SWAP		(1ULL << 62)
> diff --git a/criu/include/parasite-syscall.h b/criu/include/parasite-syscall.h
> index 15a13a6..6c78e23 100644
> --- a/criu/include/parasite-syscall.h
> +++ b/criu/include/parasite-syscall.h
> @@ -53,7 +53,6 @@ struct parasite_ctl {
>  	unsigned long		args_size;
>  	int			tsock;					/* transport socket for transfering fds */
>  
> -	struct list_head	pre_list;
>  	struct page_pipe	*mem_pp;
>  };
>  
> diff --git a/criu/include/pstree.h b/criu/include/pstree.h
> index 327ad49..b01cc9e 100644
> --- a/criu/include/pstree.h
> +++ b/criu/include/pstree.h
> @@ -43,6 +43,8 @@ struct dmp_info {
>  	 * threads. Dumping tasks with different creds is not supported.
>  	 */
>  	struct proc_status_creds *pi_creds;
> +
> +	struct parasite_ctl *parasite_ctl;
>  };
>  
>  static inline struct dmp_info *dmpi(struct pstree_item *i)
> diff --git a/criu/mem.c b/criu/mem.c
> index db61aed..d619a72 100644
> --- a/criu/mem.c
> +++ b/criu/mem.c
> @@ -187,7 +187,7 @@ static int generate_iovs(struct vma_area *vma, struct page_pipe *pp, u64 *map, u
>  }
>  
>  static struct parasite_dump_pages_args *prep_dump_pages_args(struct parasite_ctl *ctl,
> -		struct vm_area_list *vma_area_list, struct page_pipe **pp_ret)
> +		struct vm_area_list *vma_area_list, bool delayed_dump)
>  {
>  	struct parasite_dump_pages_args *args;
>  	struct parasite_vma_entry *p_vma;
> @@ -205,7 +205,7 @@ static struct parasite_dump_pages_args *prep_dump_pages_args(struct parasite_ctl
>  		 * Kernel write to aio ring is not soft-dirty tracked,
>  		 * so we ignore them at pre-dump.
>  		 */
> -		if (vma_entry_is(vma->e, VMA_AREA_AIORING) && pp_ret)
> +		if (vma_entry_is(vma->e, VMA_AREA_AIORING) && delayed_dump)
>  			continue;
>  		if (vma->e->prot & PROT_READ)
>  			continue;
> @@ -266,7 +266,7 @@ static int dump_pages(struct page_pipe *pp, struct parasite_ctl *ctl,
>  static int __parasite_dump_pages_seized(struct parasite_ctl *ctl,
>  		struct parasite_dump_pages_args *args,
>  		struct vm_area_list *vma_area_list,
> -		struct page_pipe **pp_ret)
> +		bool delayed_dump)
>  {
>  	pmc_t pmc = PMC_INIT;
>  	struct page_pipe *pp;
> @@ -292,12 +292,13 @@ static int __parasite_dump_pages_seized(struct parasite_ctl *ctl,
>  		return -1;
>  
>  	ret = -1;
> -	pp = create_page_pipe(vma_area_list->priv_size,
> -			      pargs_iovs(args), pp_ret == NULL);
> +
> +	ctl->mem_pp = pp = create_page_pipe(vma_area_list->priv_size,
> +					    pargs_iovs(args), !delayed_dump);
>  	if (!pp)
>  		goto out;
>  
> -	if (pp_ret == NULL) {
> +	if (!delayed_dump) {
>  		ret = open_page_xfer(&xfer, CR_FD_PAGEMAP, ctl->pid.virt);
>  		if (ret < 0)
>  			goto out_pp;
> @@ -322,7 +323,7 @@ static int __parasite_dump_pages_seized(struct parasite_ctl *ctl,
>  		if (!vma_area_is_private(vma_area, kdat.task_size))
>  			continue;
>  		if (vma_entry_is(vma_area->e, VMA_AREA_AIORING)) {
> -			if (pp_ret)
> +			if (delayed_dump)
>  				continue;
>  			has_parent = false;
>  		}
> @@ -333,7 +334,7 @@ static int __parasite_dump_pages_seized(struct parasite_ctl *ctl,
>  again:
>  		ret = generate_iovs(vma_area, pp, map, &off, has_parent);
>  		if (ret == -EAGAIN) {
> -			BUG_ON(pp_ret);
> +			BUG_ON(delayed_dump);
>  
>  			ret = dump_pages(pp, ctl, args, &xfer);
>  			if (ret)
> @@ -345,25 +346,22 @@ again:
>  			goto out_xfer;
>  	}
>  
> -	ret = dump_pages(pp, ctl, args, pp_ret ? NULL : &xfer);
> +	ret = dump_pages(pp, ctl, args, delayed_dump ? NULL : &xfer);
>  	if (ret)
>  		goto out_xfer;
>  
>  	timing_stop(TIME_MEMDUMP);
>  
> -	if (pp_ret)
> -		*pp_ret = pp;
> -
>  	/*
>  	 * Step 4 -- clean up
>  	 */
>  
>  	ret = task_reset_dirty_track(ctl->pid.real);
>  out_xfer:
> -	if (pp_ret == NULL)
> +	if (!delayed_dump)
>  		xfer.close(&xfer);
>  out_pp:
> -	if (ret || !pp_ret)
> +	if (ret || !delayed_dump)
>  		destroy_page_pipe(pp);
>  out:
>  	pmc_fini(&pmc);
> @@ -372,12 +370,12 @@ out:
>  }
>  
>  int parasite_dump_pages_seized(struct parasite_ctl *ctl,
> -		struct vm_area_list *vma_area_list, struct page_pipe **pp)
> +		struct vm_area_list *vma_area_list, bool delayed_dump)
>  {
>  	int ret;
>  	struct parasite_dump_pages_args *pargs;
>  
> -	pargs = prep_dump_pages_args(ctl, vma_area_list, pp);
> +	pargs = prep_dump_pages_args(ctl, vma_area_list, delayed_dump);
>  
>  	/*
>  	 * Add PROT_READ protection for all VMAs we're about to
> @@ -399,7 +397,8 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl,
>  		return -1;
>  	}
>  
> -	ret = __parasite_dump_pages_seized(ctl, pargs, vma_area_list, pp);
> +	ret = __parasite_dump_pages_seized(ctl, pargs, vma_area_list,
> +					   delayed_dump);
>  
>  	if (ret) {
>  		pr_err("Can't dump page with parasite\n");
> diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c
> index c2467dc..29964a9 100644
> --- a/criu/parasite-syscall.c
> +++ b/criu/parasite-syscall.c
> @@ -1434,6 +1434,8 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
>  	if (parasite_start_daemon(ctl, item))
>  		goto err_restore;
>  
> +	dmpi(item)->parasite_ctl = ctl;
> +
>  	return ctl;
>  
>  err_restore:
> -- 
> 1.9.1
> 
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu


More information about the CRIU mailing list