[CRIU] [PATCH v3 03/11] gc: implement link remaps deletion

Pavel Emelyanov xemul at virtuozzo.com
Tue Aug 23 05:09:00 PDT 2016


On 08/10/2016 10:12 PM, Eugene Batalov wrote:
> We reuse minimal subset of criu restore command logic sufficient
> to locate all the link remaps in all ps tree mnt namespaces.
> No ps tree processes are created but all the ps tree mnt
> namespaces and mountpoints are created. After creation of ps
> tree mnt namespaces each link remap is deleted in its namespace.
> 
> Signed-off-by: Eugene Batalov <eabatalov89 at gmail.com>
> ---
>  criu/cr-gc.c             | 122 ++++++++++++++++++++++++++++++++++++++++++++++-
>  criu/files-reg.c         |  48 +++++++++++++++++--
>  criu/include/files-reg.h |   1 +
>  3 files changed, 165 insertions(+), 6 deletions(-)
> 
> diff --git a/criu/cr-gc.c b/criu/cr-gc.c
> index bdd3723..d6b4ad1 100644
> --- a/criu/cr-gc.c
> +++ b/criu/cr-gc.c
> @@ -1,6 +1,126 @@
> +#include <sched.h>
> +#include <unistd.h>
> +
> +#include "criu-log.h"
>  #include "crtools.h"
> +#include "pstree.h"
> +#include "files.h"
> +#include "files-reg.h"
> +#include "mount.h"
> +#include "cr_options.h"
> +#include "namespaces.h"
> +#include "util.h"
>  
> -int cr_gc(void)
> +static int gc_validate_opts(void)
> +{
> +	/*
> +	 * To work properly gc should be done in the same environment as
> +	 * dump was done in. So prohibit environment changes on gc.
> +	 */
> +	if (opts.unshare_flags)  {
> +		pr_err("Unshare options are not compatible with gc command\n");
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +static int root_mntns = -1;
> +
> +static int gc_setup_mntns(void)
> +{
> +	if (mntns_maybe_create_roots() < 0)
> +		return -1;
> +
> +	if (read_mnt_ns_img() < 0)
> +		return -1;
> +
> +	if (root_ns_mask & CLONE_NEWNS) {
> +		/* prepare_mnt_ns() expects that root mnt ns is already created */
> +		if (unshare(CLONE_NEWNS)) {
> +			pr_perror("Couldn't create root mount namespace\n");
> +			return -1;
> +		}
> +
> +		root_mntns = open_proc(PROC_SELF, "ns/mnt");
> +		if (root_mntns < 0)
> +			return -1;
> +	}
> +
> +	if (prepare_mnt_ns() < 0)
> +		return -1;
> +
> +	if (prepare_remaps() < 0)
> +		return -1;
> +
> +	return 0;
> +}
> +
> +static int gc_cleanup_mntns(void)
> +{
> +	int ret = depopulate_roots_yard(root_mntns, false);
> +
> +	if ((root_mntns != -1) && close(root_mntns)) {
> +		pr_perror("Couldn't close root mntns fd");
> +		ret = -1;
> +	}
> +
> +	return ret;
> +}
> +
> +static int gc_do(void)
>  {
> +	if (gc_link_remaps() < 0)
> +		return -1;
> +
>  	return 0;
>  }
> +
> +int cr_gc(void)
> +{
> +	int ret = 0;
> +
> +	if (gc_validate_opts() < 0) {
> +		ret = -1;
> +		goto exit;
> +	}
> +
> +	if (check_img_inventory() < 0) {
> +		ret = -1;
> +		goto exit;
> +	}
> +
> +	if (prepare_task_entries() < 0) {
> +		ret = -1;
> +		goto exit;
> +	}
> +
> +	if (prepare_pstree() < 0) {
> +		ret = -1;
> +		goto exit;
> +	}
> +
> +	if (prepare_shared_fdinfo() < 0) {
> +		ret = -1;
> +		goto exit;
> +	}
> +
> +	if (collect_remaps_and_regfiles()) {
> +		ret = -1;
> +		goto exit;
> +	}

Can you describe why you need all of the above?

> +
> +	if (gc_setup_mntns()) {
> +		ret = -1;
> +		goto exit;
> +	}
> +
> +	if (gc_do())
> +		ret = -1;
> +
> +exit:
> +	if (gc_cleanup_mntns())
> +		ret = -1;
> +
> +	return ret;
> +}
> diff --git a/criu/files-reg.c b/criu/files-reg.c
> index 03ad363..efb7045 100644
> --- a/criu/files-reg.c
> +++ b/criu/files-reg.c
> @@ -523,11 +523,12 @@ static void try_clean_ghost(struct remap_info *ri)
>  	pr_perror(" `- XFail [%s] ghost", path);
>  }
>  
> -static int clean_one_remap(struct file_remap *remap)
> +static int clean_one_remap(struct file_remap *remap, int rmntns_root)
>  {
> -	int rmntns_root, ret = 0;
> +	int ret = 0;
>  
> -	rmntns_root = mntns_get_root_by_mnt_id(remap->rmnt_id);
> +	if (rmntns_root == -1)
> +		rmntns_root = mntns_get_root_by_mnt_id(remap->rmnt_id);
>  	if (rmntns_root < 0)
>  		return -1;
>  
> @@ -625,7 +626,7 @@ void remap_put(struct file_remap *remap)
>  {
>  	mutex_lock(ghost_file_mutex);
>  	if (--remap->users == 0)
> -		clean_one_remap(remap);
> +		clean_one_remap(remap, -1);
>  	mutex_unlock(ghost_file_mutex);
>  }
>  
> @@ -711,6 +712,43 @@ static void __rollback_link_remaps(bool do_unlink)
>  void delete_link_remaps(void) { __rollback_link_remaps(true); }
>  void free_link_remaps(void) { __rollback_link_remaps(false); }
>  
> +int gc_link_remaps(void)
> +{
> +	struct remap_info *ri;
> +	struct file_remap *remap;
> +
> +	list_for_each_entry(ri, &remaps, list) {
> +		if (ri->rfe->remap_type != REMAP_TYPE__LINKED)
> +			continue;
> +
> +		remap = ri->rfi->remap;
> +		struct ns_id *remap_mntns = lookup_nsid_by_mnt_id(remap->rmnt_id);
> +
> +		if (!remap_mntns) {
> +			pr_err("Can't get remap %s mnt ns %d\n",
> +					remap->rpath, remap->rmnt_id);
> +			return -1;
> +		}
> +
> +		if (remap_mntns->nd->cflag != CLONE_NEWNS) {
> +			pr_err("Wrong clone flag of remap mntns %x (id:%d)",
> +					remap_mntns->nd->cflag, remap->rmnt_id);
> +			return -1;
> +		}
> +
> +		/*
> +		 * We are root ps tree item in restore cmd terms.
> +		 * All the mnt namespaces and their fds are created
> +		 * by root ps tree item on restore.
> +		 * So we can simply use mnt ns fds here.
> +		 */
> +		if (clean_one_remap(remap, remap_mntns->mnt.root_fd))
> +			return -1;
> +	}
> +
> +	return 0;
> +}
> +
>  static int create_link_remap(char *path, int len, int lfd,
>  				u32 *idp, struct ns_id *nsid)
>  {
> @@ -1500,7 +1538,7 @@ ext:
>  
>  		BUG_ON(!rfi->remap->users);
>  		if (--rfi->remap->users == 0)
> -			clean_one_remap(rfi->remap);
> +			clean_one_remap(rfi->remap, -1);
>  
>  		mutex_unlock(ghost_file_mutex);
>  	}
> diff --git a/criu/include/files-reg.h b/criu/include/files-reg.h
> index 6cc2454..ff54303 100644
> --- a/criu/include/files-reg.h
> +++ b/criu/include/files-reg.h
> @@ -52,6 +52,7 @@ extern void delete_link_remaps(void);
>  extern void free_link_remaps(void);
>  extern int prepare_remaps(void);
>  extern void try_clean_remaps(void);
> +extern int gc_link_remaps(void);
>  
>  extern int strip_deleted(struct fd_link *link);
>  
> 



More information about the CRIU mailing list