[CRIU] [PATCH v2 03/12] gc: implement link remaps deletion

Eugene Batalov eabatalov89 at gmail.com
Sat Aug 6 11:26:26 PDT 2016


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;
+	}
+
+	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 2b7a211..8a0ec1d 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)
 {
@@ -1490,7 +1528,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);
 
-- 
1.9.1



More information about the CRIU mailing list