[v4,04/12] gc: implement link remaps deletion

Submitted by Eugene Batalov on Sept. 11, 2016, 5:14 p.m.

Details

Message ID 1473614091-4734-5-git-send-email-eabatalov89@gmail.com
State Rejected
Series "Series without cover letter"
Headers show

Commit Message

Eugene Batalov Sept. 11, 2016, 5:14 p.m.
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.

Exact logic is the following:
1. check_img_inventory() - prepare_pstree(). These calls are needed to
   initialize root_ns_mask that is used during ps tree mnt namespaces
   creation.

2. prepare_shared_fdinfo() - collect_remaps_and_regfiles(). These calls
   are needed to collect information about link remaps and reg files of
   ps tree from dump.

3. gc_setup_mntns() (if needed) creates all the ps tree mnt namespaces
   and performs mounting of proper fs hierachies into them.

4. prepare_remaps() call is needed to associate link remaps and reg
   files structs we've read from dump. It also works with ps tree fs
   so mnt namespaces should be created before this call.

5. gc_link_remaps() - delete all the link remaps in their mnt namespaces.

Signed-off-by: Eugene Batalov <eabatalov89@gmail.com>
---
 criu/cr-gc.c             | 104 ++++++++++++++++++++++++++++++++++++++++++++++-
 criu/files-reg.c         |  37 +++++++++++++++++
 criu/include/files-reg.h |   1 +
 3 files changed, 141 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/criu/cr-gc.c b/criu/cr-gc.c
index bdd3723..e248e66 100644
--- a/criu/cr-gc.c
+++ b/criu/cr-gc.c
@@ -1,6 +1,108 @@ 
+#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 "namespaces.h"
+#include "util.h"
 
-int cr_gc(void)
+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;
+
+	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 (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;
+	}
+
+	if (gc_setup_mntns()) {
+		ret = -1;
+		goto exit;
+	}
+
+	if (prepare_remaps() < 0) {
+		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 45100f9..07e9772 100644
--- a/criu/files-reg.c
+++ b/criu/files-reg.c
@@ -712,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)
 {
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);
 

Comments

Pavel Emelianov Oct. 12, 2016, 8:54 a.m.
On 09/11/2016 08:14 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.
> 
> Exact logic is the following:
> 1. check_img_inventory() - prepare_pstree(). These calls are needed to
>    initialize root_ns_mask that is used during ps tree mnt namespaces
>    creation.

The root_ns_mask() is set up only in prepare_pstree() (which does much
more than just this). But what is check_img_inventory() for?

> 2. prepare_shared_fdinfo() - collect_remaps_and_regfiles(). These calls
>    are needed to collect information about link remaps and reg files of
>    ps tree from dump.

Why prepare_shared_fdinfo() needed?

> 3. gc_setup_mntns() (if needed) creates all the ps tree mnt namespaces
>    and performs mounting of proper fs hierachies into them.

The read_mntns_img() does this, no?

> 4. prepare_remaps() call is needed to associate link remaps and reg
>    files structs we've read from dump. It also works with ps tree fs
>    so mnt namespaces should be created before this call.
> 
> 5. gc_link_remaps() - delete all the link remaps in their mnt namespaces.
> 
> Signed-off-by: Eugene Batalov <eabatalov89@gmail.com>
> ---
>  criu/cr-gc.c             | 104 ++++++++++++++++++++++++++++++++++++++++++++++-
>  criu/files-reg.c         |  37 +++++++++++++++++
>  criu/include/files-reg.h |   1 +
>  3 files changed, 141 insertions(+), 1 deletion(-)
> 
> diff --git a/criu/cr-gc.c b/criu/cr-gc.c
> index bdd3723..e248e66 100644
> --- a/criu/cr-gc.c
> +++ b/criu/cr-gc.c
> @@ -1,6 +1,108 @@
> +#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 "namespaces.h"
> +#include "util.h"
>  
> -int cr_gc(void)
> +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;
> +
> +	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 (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;
> +	}
> +
> +	if (gc_setup_mntns()) {
> +		ret = -1;
> +		goto exit;
> +	}
> +
> +	if (prepare_remaps() < 0) {
> +		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 45100f9..07e9772 100644
> --- a/criu/files-reg.c
> +++ b/criu/files-reg.c
> @@ -712,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)
>  {
> 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);
>  
>
Eugene Batalov Oct. 24, 2016, 8:57 p.m.
2016-10-12 11:54 GMT+03:00 Pavel Emelyanov <xemul@virtuozzo.com>:

> On 09/11/2016 08:14 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.
> >
> > Exact logic is the following:
> > 1. check_img_inventory() - prepare_pstree(). These calls are needed to
> >    initialize root_ns_mask that is used during ps tree mnt namespaces
> >    creation.
>
> The root_ns_mask() is set up only in prepare_pstree() (which does much
> more than just this). But what is check_img_inventory() for?
>

check_img_inventory() call is intended to check that criu dump files that
we pass to criu gc are supported and somewhat valid.
check_img_inventory() is also called in the beginning of criu restore and
cr_lazy_pages.
So it looks like we should have it in cr-gc.


>
> > 2. prepare_shared_fdinfo() - collect_remaps_and_regfiles(). These calls
> >    are needed to collect information about link remaps and reg files of
> >    ps tree from dump.
>
> Why prepare_shared_fdinfo() needed?
>

prepare_shared_fdinfo() is needed because
during collect_remaps_and_regfiles() call collect_one_regfile() is called
and collect_one_regfile() calls file_desc_add().


>
> > 3. gc_setup_mntns() (if needed) creates all the ps tree mnt namespaces
> >    and performs mounting of proper fs hierachies into them.
>
> The read_mntns_img() does this, no?
>

No. The whole logic of gc_setup_mntns() does this. The main component
of gc_setup_mntns() is prepare_mnt_ns() call that instantiates
all the ps tree mnt namespaces and their root file systems.


>
> > 4. prepare_remaps() call is needed to associate link remaps and reg
> >    files structs we've read from dump. It also works with ps tree fs
> >    so mnt namespaces should be created before this call.
> >
> > 5. gc_link_remaps() - delete all the link remaps in their mnt namespaces.
> >
> > Signed-off-by: Eugene Batalov <eabatalov89@gmail.com>
> > ---
> >  criu/cr-gc.c             | 104 ++++++++++++++++++++++++++++++
> ++++++++++++++++-
> >  criu/files-reg.c         |  37 +++++++++++++++++
> >  criu/include/files-reg.h |   1 +
> >  3 files changed, 141 insertions(+), 1 deletion(-)
> >
> > diff --git a/criu/cr-gc.c b/criu/cr-gc.c
> > index bdd3723..e248e66 100644
> > --- a/criu/cr-gc.c
> > +++ b/criu/cr-gc.c
> > @@ -1,6 +1,108 @@
> > +#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 "namespaces.h"
> > +#include "util.h"
> >
> > -int cr_gc(void)
> > +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;
> > +
> > +     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 (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;
> > +     }
> > +
> > +     if (gc_setup_mntns()) {
> > +             ret = -1;
> > +             goto exit;
> > +     }
> > +
> > +     if (prepare_remaps() < 0) {
> > +             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 45100f9..07e9772 100644
> > --- a/criu/files-reg.c
> > +++ b/criu/files-reg.c
> > @@ -712,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)
> >  {
> > 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);
> >
> >
>
>
Pavel Emelianov Oct. 25, 2016, 12:50 p.m.
On 10/24/2016 11:57 PM, Eugene Batalov wrote:
> 2016-10-12 11:54 GMT+03:00 Pavel Emelyanov <xemul@virtuozzo.com <mailto:xemul@virtuozzo.com>>:
> 
>     On 09/11/2016 08:14 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.
>     >
>     > Exact logic is the following:
>     > 1. check_img_inventory() - prepare_pstree(). These calls are needed to
>     >    initialize root_ns_mask that is used during ps tree mnt namespaces
>     >    creation.
> 
>     The root_ns_mask() is set up only in prepare_pstree() (which does much
>     more than just this). But what is check_img_inventory() for?
> 
> 
> check_img_inventory() call is intended to check that criu dump files that we pass to criu gc are supported and somewhat valid.
> check_img_inventory() is also called in the beginning of criu restore and cr_lazy_pages.
> So it looks like we should have it in cr-gc.

OK

> 
> 
>     > 2. prepare_shared_fdinfo() - collect_remaps_and_regfiles(). These calls
>     >    are needed to collect information about link remaps and reg files of
>     >    ps tree from dump.
> 
>     Why prepare_shared_fdinfo() needed?
> 
> 
> prepare_shared_fdinfo() is needed because during collect_remaps_and_regfiles() call collect_one_regfile() is called
> and collect_one_regfile() calls file_desc_add().

Got it. Please, rename prepare_shared_fdinfo() into prepare_files() :)

> 
> 
>     > 3. gc_setup_mntns() (if needed) creates all the ps tree mnt namespaces
>     >    and performs mounting of proper fs hierachies into them.
> 
>     The read_mntns_img() does this, no?
> 
> 
> No. The whole logic of gc_setup_mntns() does this. The main component of gc_setup_mntns() is prepare_mnt_ns() call that instantiates
> all the ps tree mnt namespaces and their root file systems.
>

Mm... So what exact objects do you need initialized by this?

> 
> 
>     > 4. prepare_remaps() call is needed to associate link remaps and reg
>     >    files structs we've read from dump. It also works with ps tree fs
>     >    so mnt namespaces should be created before this call.
>     >
>     > 5. gc_link_remaps() - delete all the link remaps in their mnt namespaces.
>     >
>     > Signed-off-by: Eugene Batalov <eabatalov89@gmail.com <mailto:eabatalov89@gmail.com>>
>     > ---
>     >  criu/cr-gc.c             | 104 ++++++++++++++++++++++++++++++++++++++++++++++-
>     >  criu/files-reg.c         |  37 +++++++++++++++++
>     >  criu/include/files-reg.h |   1 +
>     >  3 files changed, 141 insertions(+), 1 deletion(-)
>     >
>     > diff --git a/criu/cr-gc.c b/criu/cr-gc.c
>     > index bdd3723..e248e66 100644
>     > --- a/criu/cr-gc.c
>     > +++ b/criu/cr-gc.c
>     > @@ -1,6 +1,108 @@
>     > +#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 "namespaces.h"
>     > +#include "util.h"
>     >
>     > -int cr_gc(void)
>     > +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;
>     > +
>     > +     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 (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;
>     > +     }
>     > +
>     > +     if (gc_setup_mntns()) {
>     > +             ret = -1;
>     > +             goto exit;
>     > +     }
>     > +
>     > +     if (prepare_remaps() < 0) {
>     > +             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 45100f9..07e9772 100644
>     > --- a/criu/files-reg.c
>     > +++ b/criu/files-reg.c
>     > @@ -712,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)
>     >  {
>     > 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);
>     >
>     >
> 
> 
> 
> 
> -- 
> Best regards,
> Eugene Batalov.
Eugene Batalov Oct. 25, 2016, 6:51 p.m.
2016-10-25 15:50 GMT+03:00 Pavel Emelyanov <xemul@virtuozzo.com>:

> On 10/24/2016 11:57 PM, Eugene Batalov wrote:
> > 2016-10-12 11:54 GMT+03:00 Pavel Emelyanov <xemul@virtuozzo.com <mailto:
> xemul@virtuozzo.com>>:
> >
> >     On 09/11/2016 08:14 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.
> >     >
> >     > Exact logic is the following:
> >     > 1. check_img_inventory() - prepare_pstree(). These calls are
> needed to
> >     >    initialize root_ns_mask that is used during ps tree mnt
> namespaces
> >     >    creation.
> >
> >     The root_ns_mask() is set up only in prepare_pstree() (which does
> much
> >     more than just this). But what is check_img_inventory() for?
> >
> >
> > check_img_inventory() call is intended to check that criu dump files
> that we pass to criu gc are supported and somewhat valid.
> > check_img_inventory() is also called in the beginning of criu restore
> and cr_lazy_pages.
> > So it looks like we should have it in cr-gc.
>
> OK
>
> >
> >
> >     > 2. prepare_shared_fdinfo() - collect_remaps_and_regfiles(). These
> calls
> >     >    are needed to collect information about link remaps and reg
> files of
> >     >    ps tree from dump.
> >
> >     Why prepare_shared_fdinfo() needed?
> >
> >
> > prepare_shared_fdinfo() is needed because during
> collect_remaps_and_regfiles() call collect_one_regfile() is called
> > and collect_one_regfile() calls file_desc_add().
>
> Got it. Please, rename prepare_shared_fdinfo() into prepare_files() :)
>

Ok.


>
> >
> >
> >     > 3. gc_setup_mntns() (if needed) creates all the ps tree mnt
> namespaces
> >     >    and performs mounting of proper fs hierachies into them.
> >
> >     The read_mntns_img() does this, no?
> >
> >
> > No. The whole logic of gc_setup_mntns() does this. The main component of
> gc_setup_mntns() is prepare_mnt_ns() call that instantiates
> > all the ps tree mnt namespaces and their root file systems.
> >
>
> Mm... So what exact objects do you need initialized by this?
>

So we need to delete link remaps. Link remaps are created by criu dump.
They are created on some fs mounted on some mount point that belong to fs
hierarchy of some mnt namespace. Process tree may have many mnt namespaces.
We have information about all the link remaps in dump files. Each link
remap information has path from root of namespace where link remaps fs is
mounted.
So if we recreate all the mnt namespaces and fs hierarchies then we'll be
able to delete all the link remaps. We do the same on criu restore so let's
reuse the logic. The logic is reused by gc_setup_mntns().

gc_setup_mntns() does:
1. Call mntns_maybe_create_roots(). It creates root yard if it is needed.
This allows to create fs hierarchies of non root ps tree (nested) mnt
namespaces.
2. read_mnt_ns_img() - to read information about all the mountpoints in all
the ps tree mnt namespaces from dump files.
3. if (root_ns_mask & CLONE_NEWNS) { unshare(CLONE_NEWNS); } because the
next call to prepare_mnt_ns() expects that root mnt ns  is created and
current process is in it.
4. Call prepare_mnt_ns()  to create all the non root ps tree mnt namespaces
and setup all fs hierarchies in all the mnt namespaces.

After that all the ps tree mnt namespaces are created and we can delete
link remaps inside them.


> >
> >
> >     > 4. prepare_remaps() call is needed to associate link remaps and reg
> >     >    files structs we've read from dump. It also works with ps tree
> fs
> >     >    so mnt namespaces should be created before this call.
> >     >
> >     > 5. gc_link_remaps() - delete all the link remaps in their mnt
> namespaces.
> >     >
> >     > Signed-off-by: Eugene Batalov <eabatalov89@gmail.com <mailto:
> eabatalov89@gmail.com>>
> >     > ---
> >     >  criu/cr-gc.c             | 104 ++++++++++++++++++++++++++++++
> ++++++++++++++++-
> >     >  criu/files-reg.c         |  37 +++++++++++++++++
> >     >  criu/include/files-reg.h |   1 +
> >     >  3 files changed, 141 insertions(+), 1 deletion(-)
> >     >
> >     > diff --git a/criu/cr-gc.c b/criu/cr-gc.c
> >     > index bdd3723..e248e66 100644
> >     > --- a/criu/cr-gc.c
> >     > +++ b/criu/cr-gc.c
> >     > @@ -1,6 +1,108 @@
> >     > +#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 "namespaces.h"
> >     > +#include "util.h"
> >     >
> >     > -int cr_gc(void)
> >     > +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;
> >     > +
> >     > +     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 (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;
> >     > +     }
> >     > +
> >     > +     if (gc_setup_mntns()) {
> >     > +             ret = -1;
> >     > +             goto exit;
> >     > +     }
> >     > +
> >     > +     if (prepare_remaps() < 0) {
> >     > +             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 45100f9..07e9772 100644
> >     > --- a/criu/files-reg.c
> >     > +++ b/criu/files-reg.c
> >     > @@ -712,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)
> >     >  {
> >     > 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);
> >     >
> >     >
> >
> >
> >
> >
> > --
> > Best regards,
> > Eugene Batalov.
>
>