[CRIU] [PATCH 13/14] mount: use per-namespace mntinfo_tree

Andrey Vagin avagin at openvz.org
Thu Apr 17 12:24:07 PDT 2014


This patch removes the global mntinfo_tree and collect_mount_info where
it was constructed.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 cr-check.c      |  5 -----
 cr-dump.c       | 12 ----------
 cr-restore.c    |  3 ---
 files-reg.c     | 70 ++++++++++++++++++++++++++++++++++++++++++---------------
 include/mount.h |  6 +++--
 mount.c         | 61 +++++++++++++++++++++++++++++--------------------
 sk-unix.c       | 13 ++++++++++-
 7 files changed, 105 insertions(+), 65 deletions(-)

diff --git a/cr-check.c b/cr-check.c
index 14f1e4d..f7ca39c 100644
--- a/cr-check.c
+++ b/cr-check.c
@@ -554,11 +554,6 @@ int cr_check(void)
 	if (mntinfo == NULL)
 		return -1;
 
-	if (collect_mount_info(getpid())) {
-		pr_err("Can't collect mount infos\n");
-		return -1;
-	}
-
 	ret |= check_map_files();
 	ret |= check_sock_diag();
 	ret |= check_ns_last_pid();
diff --git a/cr-dump.c b/cr-dump.c
index c3e6466..110642f 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -1656,12 +1656,6 @@ int cr_pre_dump_tasks(pid_t pid)
 	if (gen_predump_ns_mask())
 		goto err;
 
-	if (collect_mount_info(pid))
-		goto err;
-
-	if (mntns_collect_root(root_item->pid.real) < 0)
-		goto err;
-
 	if (collect_mnt_namespaces() < 0)
 		goto err;
 
@@ -1769,12 +1763,6 @@ int cr_dump_tasks(pid_t pid)
 	if (collect_file_locks())
 		goto err;
 
-	if (collect_mount_info(pid))
-		goto err;
-
-	if (mntns_collect_root(root_item->pid.real) < 0)
-		goto err;
-
 	if (dump_mnt_namespaces() < 0)
 		goto err;
 
diff --git a/cr-restore.c b/cr-restore.c
index 2cdcb08..316d7fb 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -1246,9 +1246,6 @@ static int restore_task_with_children(void *_arg)
 		if (restore_finish_stage(CR_STATE_RESTORE_NS) < 0)
 			exit(1);
 
-		if (collect_mount_info(getpid()))
-			exit(1);
-
 		if (prepare_namespace(current, ca->clone_flags))
 			exit(1);
 
diff --git a/files-reg.c b/files-reg.c
index 3d316ec..6bc3a80 100644
--- a/files-reg.c
+++ b/files-reg.c
@@ -23,6 +23,7 @@
 #include "fs-magic.h"
 #include "asm/atomic.h"
 #include "namespaces.h"
+#include "proc_parse.h"
 
 #include "protobuf.h"
 #include "protobuf/regfile.pb-c.h"
@@ -56,6 +57,7 @@ static mutex_t *ghost_file_mutex;
  */
 struct link_remap_rlb {
 	struct list_head	list;
+	pid_t			pid;
 	char			*path;
 };
 static LIST_HEAD(link_remaps);
@@ -72,6 +74,7 @@ static int open_remap_ghost(struct reg_file_info *rfi,
 	struct ghost_file *gf;
 	GhostFileEntry *gfe = NULL;
 	int gfd, ifd, ghost_flags;
+	char *root, path[PATH_MAX];
 
 	rfe->remap_id &= ~REMAP_GHOST;
 	list_for_each_entry(gf, &ghost_files, list)
@@ -86,6 +89,12 @@ static int open_remap_ghost(struct reg_file_info *rfi,
 
 	pr_info("Opening ghost file %#x for %s\n", rfe->remap_id, rfi->path);
 
+	root = rst_get_mnt_root(rfi->rfe->mnt_id);
+	if (root == NULL) {
+		pr_err("The %d mount is not found\n", rfi->rfe->mnt_id);
+		return -1;
+	}
+
 	gf = shmalloc(sizeof(*gf));
 	if (!gf)
 		return -1;
@@ -119,9 +128,10 @@ static int open_remap_ghost(struct reg_file_info *rfi,
 	} else
 		ghost_flags = O_WRONLY | O_CREAT | O_EXCL;
 
-	gfd = open(gf->remap.path, ghost_flags, gfe->mode);
+	snprintf(path, sizeof(path), "%s/%s", root, gf->remap.path);
+	gfd = open(path, ghost_flags, gfe->mode);
 	if (gfd < 0) {
-		pr_perror("Can't open ghost file %s", gf->remap.path);
+		pr_perror("Can't open ghost file %s", path);
 		goto close_ifd;
 	}
 
@@ -290,7 +300,8 @@ struct file_remap *lookup_ghost_remap(u32 dev, u32 ino)
 	return NULL;
 }
 
-static int dump_ghost_remap(char *path, const struct stat *st, int lfd, u32 id)
+static int dump_ghost_remap(char *path, const struct stat *st,
+				int lfd, u32 id, struct mount_info *mi)
 {
 	struct ghost_file *gf;
 	RemapFilePathEntry rpe = REMAP_FILE_PATH_ENTRY__INIT;
@@ -304,7 +315,7 @@ static int dump_ghost_remap(char *path, const struct stat *st, int lfd, u32 id)
 		return -1;
 	}
 
-	phys_dev = phys_stat_resolve_dev(st->st_dev, path);
+	phys_dev = phys_stat_resolve_dev(mi->nsid->mnt.mntinfo_tree, st->st_dev, path);
 	list_for_each_entry(gf, &ghost_files, list)
 		if ((gf->dev == phys_dev) && (gf->ino == st->st_ino))
 			goto dump_entry;
@@ -339,9 +350,10 @@ static void __rollback_link_remaps(bool do_unlink)
 	if (!opts.link_remap_ok)
 		return;
 
-	mntns_root = get_service_fd(ROOT_FD_OFF);
-
 	list_for_each_entry_safe(rlb, tmp, &link_remaps, list) {
+		mntns_root = mntns_collect_root(rlb->pid);
+		if (mntns_root < 0)
+			return;
 		list_del(&rlb->list);
 		if (do_unlink)
 			unlinkat(mntns_root, rlb->path, 0);
@@ -353,7 +365,8 @@ 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); }
 
-static int create_link_remap(char *path, int len, int lfd, u32 *idp)
+static int create_link_remap(char *path, int len, int lfd,
+				u32 *idp, struct mount_info *mi)
 {
 	char link_name[PATH_MAX], *tmp;
 	RegFileEntry rfe = REG_FILE_ENTRY__INIT;
@@ -394,7 +407,7 @@ static int create_link_remap(char *path, int len, int lfd, u32 *idp)
 	/* Any 'unique' name works here actually. Remap works by reg-file ids. */
 	snprintf(tmp + 1, sizeof(link_name) - (size_t)(tmp - link_name - 1), "link_remap.%d", rfe.id);
 
-	mntns_root = get_service_fd(ROOT_FD_OFF);
+	mntns_root = mntns_collect_root(mi->nsid->pid);
 
 	if (linkat(lfd, "", mntns_root, link_name, AT_EMPTY_PATH) < 0) {
 		pr_perror("Can't link remap to %s", path);
@@ -411,6 +424,8 @@ static int create_link_remap(char *path, int len, int lfd, u32 *idp)
 	if (rlb)
 		rlb->path = strdup(link_name);
 
+	rlb->pid = mi->nsid->pid;
+
 	if (!rlb || !rlb->path) {
 		pr_perror("Can't register rollback for %s", path);
 		xfree(rlb ? rlb->path : NULL);
@@ -422,12 +437,13 @@ static int create_link_remap(char *path, int len, int lfd, u32 *idp)
 	return pb_write_one(fdset_fd(glob_fdset, CR_FD_REG_FILES), &rfe, PB_REG_FILE);
 }
 
-static int dump_linked_remap(char *path, int len, const struct stat *ost, int lfd, u32 id)
+static int dump_linked_remap(char *path, int len, const struct stat *ost,
+				int lfd, u32 id, struct mount_info *mi)
 {
 	u32 lid;
 	RemapFilePathEntry rpe = REMAP_FILE_PATH_ENTRY__INIT;
 
-	if (create_link_remap(path, len, lfd, &lid))
+	if (create_link_remap(path, len, lfd, &lid, mi))
 		return -1;
 
 	rpe.orig_id = id;
@@ -471,7 +487,8 @@ static inline bool nfs_silly_rename(char *rpath, const struct fd_parms *parms)
 	return (parms->fs_type == NFS_SUPER_MAGIC) && is_sillyrename_name(rpath);
 }
 
-static int check_path_remap(char *rpath, int plen, const struct fd_parms *parms, int lfd, u32 id)
+static int check_path_remap(char *rpath, int plen, const struct fd_parms *parms,
+				int lfd, u32 id, struct mount_info *mi)
 {
 	int ret, mntns_root;
 	struct stat pst;
@@ -484,7 +501,7 @@ static int check_path_remap(char *rpath, int plen, const struct fd_parms *parms,
 		 * be careful whether anybody still has any of its hardlinks
 		 * also open.
 		 */
-		return dump_ghost_remap(rpath + 1, ost, lfd, id);
+		return dump_ghost_remap(rpath + 1, ost, lfd, id, mi);
 
 	if (nfs_silly_rename(rpath, parms)) {
 		/*
@@ -495,10 +512,12 @@ static int check_path_remap(char *rpath, int plen, const struct fd_parms *parms,
 		 * links on it) to have some persistent name at hands.
 		 */
 		pr_debug("Dump silly-rename linked remap for %x\n", id);
-		return dump_linked_remap(rpath + 1, plen - 1, ost, lfd, id);
+		return dump_linked_remap(rpath + 1, plen - 1, ost, lfd, id, mi);
 	}
 
-	mntns_root = get_service_fd(ROOT_FD_OFF);
+	mntns_root = mntns_collect_root(mi->nsid->pid);
+	if (mntns_root < 0)
+		return -1;
 
 	ret = fstatat(mntns_root, rpath, &pst, 0);
 	if (ret < 0) {
@@ -510,7 +529,8 @@ static int check_path_remap(char *rpath, int plen, const struct fd_parms *parms,
 		 */
 
 		if (errno == ENOENT)
-			return dump_linked_remap(rpath + 1, plen - 1, ost, lfd, id);
+			return dump_linked_remap(rpath + 1, plen - 1,
+							ost, lfd, id, mi);
 
 		pr_perror("Can't stat path");
 		return -1;
@@ -547,6 +567,7 @@ static int check_path_remap(char *rpath, int plen, const struct fd_parms *parms,
 int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
 {
 	struct fd_link _link, *link;
+	struct mount_info *mi = NULL;
 	int rfd;
 
 	RegFileEntry rfe = REG_FILE_ENTRY__INIT;
@@ -563,6 +584,12 @@ int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
 		rfe.has_mnt_id = true;
 	}
 
+	mi = lookup_mnt_id(p->mnt_id);
+	if (mi == NULL) {
+		pr_err("Unable to look up the %d mount\n", p->mnt_id);
+		return -1;
+	}
+
 	pr_info("Dumping path for %d fd via self %d [%s]\n",
 			p->fd, lfd, &link->name[1]);
 
@@ -574,7 +601,7 @@ int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
 		return -1;
 	}
 
-	if (check_path_remap(link->name, link->len, p, lfd, id))
+	if (check_path_remap(link->name, link->len, p, lfd, id, mi))
 		return -1;
 
 	rfe.id		= id;
@@ -674,9 +701,16 @@ int open_path(struct file_desc *d,
 static int do_open_reg_noseek_flags(struct reg_file_info *rfi, void *arg)
 {
 	u32 flags = *(u32 *)arg;
-	int fd;
+	int fd, mntns_root;
+	struct mount_info *mi;
+
+	mi = lookup_mnt_id(rfi->rfe->mnt_id);
+	if (mi == NULL)
+		return -1;
+
+	mntns_root = mntns_collect_root(mi->nsid->pid);
 
-	fd = open(rfi->path, flags);
+	fd = openat(mntns_root, rfi->path, flags);
 	if (fd < 0) {
 		pr_perror("Can't open file %s on restore", rfi->path);
 		return fd;
diff --git a/include/mount.h b/include/mount.h
index 25df359..100e6e2 100644
--- a/include/mount.h
+++ b/include/mount.h
@@ -25,8 +25,10 @@ extern struct mount_info *lookup_mnt_sdev(unsigned int s_dev);
 
 extern struct ns_desc mnt_ns_desc;
 
-extern dev_t phys_stat_resolve_dev(dev_t st_dev, const char *path);
-extern bool phys_stat_dev_match(dev_t st_dev, dev_t phys_dev, const char *path);
+extern dev_t phys_stat_resolve_dev(struct mount_info *tree,
+					dev_t st_dev, const char *path);
+extern bool phys_stat_dev_match(struct mount_info *tree, dev_t st_dev,
+					dev_t phys_dev, const char *path);
 
 extern int restore_task_mnt_ns(struct ns_id *nsid, pid_t pid);
 extern int fini_mnt_ns(void);
diff --git a/mount.c b/mount.c
index d4a0ff9..92c6a6c 100644
--- a/mount.c
+++ b/mount.c
@@ -31,13 +31,6 @@
  * Single linked list of mount points get from proc/images
  */
 struct mount_info *mntinfo;
-/*
- * Tree of mount points. When required is generated from
- * the mntinfo list. Tree elements are sorted, so that it
- * represents the real FS visibility and is thus suitable
- * for umounting or path resolution.
- */
-static struct mount_info *mntinfo_tree;
 
 static int open_mountpoint(struct mount_info *pm);
 
@@ -81,6 +74,7 @@ int open_mount(unsigned int s_dev)
 	return -ENOENT;
 }
 
+<<<<<<< HEAD
 int collect_mount_info(pid_t pid)
 {
 	pr_info("Collecting mountinfo\n");
@@ -106,6 +100,8 @@ int collect_mount_info(pid_t pid)
 	return 0;
 }
 
+=======
+>>>>>>> 37cd280... mount: use per-namespace mntinfo_tree
 static struct mount_info *__lookup_mnt_id(struct mount_info *list, int id)
 {
 	struct mount_info *m;
@@ -142,7 +138,7 @@ struct mount_info *lookup_mnt_sdev(unsigned int s_dev)
 	return NULL;
 }
 
-static struct mount_info *mount_resolve_path(const char *path)
+static struct mount_info *mount_resolve_path(struct mount_info *mntinfo_tree, const char *path)
 {
 	size_t pathlen = strlen(path);
 	struct mount_info *m = mntinfo_tree, *c;
@@ -171,11 +167,12 @@ static struct mount_info *mount_resolve_path(const char *path)
 	return m;
 }
 
-dev_t phys_stat_resolve_dev(dev_t st_dev, const char *path)
+dev_t phys_stat_resolve_dev(struct mount_info *tree,
+				dev_t st_dev, const char *path)
 {
 	struct mount_info *m;
 
-	m = mount_resolve_path(path);
+	m = mount_resolve_path(tree, path);
 	/*
 	 * BTRFS returns subvolume dev-id instead of
 	 * superblock dev-id, in such case return device
@@ -185,12 +182,13 @@ dev_t phys_stat_resolve_dev(dev_t st_dev, const char *path)
 		MKKDEV(MAJOR(st_dev), MINOR(st_dev)) : m->s_dev;
 }
 
-bool phys_stat_dev_match(dev_t st_dev, dev_t phys_dev, const char *path)
+bool phys_stat_dev_match(struct mount_info *tree, dev_t st_dev,
+				dev_t phys_dev, const char *path)
 {
 	if (st_dev == kdev_to_odev(phys_dev))
 		return true;
 
-	return phys_dev == phys_stat_resolve_dev(st_dev, path);
+	return phys_dev == phys_stat_resolve_dev(tree, st_dev, path);
 }
 
 /*
@@ -888,6 +886,12 @@ int dump_mnt_ns(struct ns_id *ns)
 		if (dump_one_mountpoint(pm, img_fd))
 			goto err;
 
+	if (mntinfo == NULL)
+		mntinfo = pms;
+	else {
+		for (pm = mntinfo; pm->next != NULL; pm = pm->next);
+		pm->next = pms;
+	}
 	ret = 0;
 err:
 	close(img_fd);
@@ -1437,7 +1441,8 @@ int rst_collect_local_mntns()
 	nsid->pid = getpid();
 	futex_set(&nsid->created, 1);
 
-	if (collect_mntinfo(nsid) == NULL)
+	mntinfo = collect_mntinfo(nsid);
+	if (mntinfo == NULL)
 		return -1;
 
 	nsid->next = ns_ids;
@@ -1560,6 +1565,10 @@ static struct mount_info *read_mnt_ns_img()
 
 		nsid = nsid->next;
 	}
+
+	/* Here is not matter where the mount list is saved */
+	mntinfo = pms;
+
 	return pms;
 err:
 	return NULL;
@@ -1666,20 +1675,16 @@ static int populate_mnt_ns(int ns_pid, struct mount_info *mis)
 {
 	struct mount_info *pms;
 
-	mntinfo_tree = NULL;
-	mntinfo = mis;
-
 	if (prepare_temporary_roots())
 		return -1;
 
-	pms = mnt_build_tree(mntinfo);
+	pms = mnt_build_tree(mis);
 	if (!pms)
 		return -1;
 
 	if (validate_mounts(pms, false))
 		return -1;
 
-	mntinfo_tree = pms;
 	return mnt_tree_for_each(pms, do_mount_one);
 }
 
@@ -1748,7 +1753,7 @@ int prepare_mnt_ns(int ns_pid)
 		struct mount_info *mi;
 
 		/* moving a mount residing under a shared mount is invalid. */
-		mi = mount_resolve_path(opts.root);
+		mi = mount_resolve_path(ns.mnt.mntinfo_tree, opts.root);
 		if (mi == NULL) {
 			pr_err("Unable to find mount point for %s\n", opts.root);
 			return -1;
@@ -1842,14 +1847,15 @@ set_root:
 
 int collect_mnt_namespaces(void)
 {
-	struct mount_info *pm;
+	struct mount_info *pm, *pms;
 	struct ns_id *ns;
 	int ret = -1;
 
 	for (ns = ns_ids; ns; ns = ns->next) {
 		if (ns->pid == getpid()) {
 			if (!(root_ns_mask & CLONE_NEWNS)) {
-				if (collect_mntinfo(ns) == NULL)
+				mntinfo = collect_mntinfo(ns);
+				if (mntinfo == NULL)
 					return -1;
 			}
 			/* Skip current namespaces, which are in the list too  */
@@ -1861,9 +1867,15 @@ int collect_mnt_namespaces(void)
 
 		pr_info("Dump MNT namespace (mountpoints) %d via %d\n",
 				ns->id, ns->pid);
-		pm = collect_mntinfo(ns);
-		if (pm == NULL)
+		pms = collect_mntinfo(ns);
+		if (pms == NULL)
 			goto err;
+		if (mntinfo == NULL)
+			mntinfo = pms;
+		else {
+			for (pm = mntinfo; pm->next != NULL; pm = pm->next);
+			pm->next = pms;
+		}
 	}
 	ret = 0;
 err:
@@ -1879,7 +1891,8 @@ int dump_mnt_namespaces(void)
 		/* Skip current namespaces, which are in the list too  */
 		if (ns->pid == getpid()) {
 			if (!(root_ns_mask & CLONE_NEWNS))
-				if (collect_mntinfo(ns) == NULL)
+				mntinfo = collect_mntinfo(ns);
+				if (mntinfo == NULL)
 					return -1;
 			continue;
 		}
diff --git a/sk-unix.c b/sk-unix.c
index a36a1a1..b2ca643 100644
--- a/sk-unix.c
+++ b/sk-unix.c
@@ -25,6 +25,8 @@
 #include "mount.h"
 #include "cr-service.h"
 #include "plugin.h"
+#include "namespaces.h"
+#include "pstree.h"
 
 #include "protobuf.h"
 #include "protobuf/sk-unix.pb-c.h"
@@ -366,8 +368,16 @@ static int unix_collect_one(const struct unix_diag_msg *m,
 {
 	struct unix_sk_desc *d;
 	char *name = NULL;
+	struct ns_id *ns;
 	int ret = 0;
 
+	ns = lookup_ns_by_id(root_item->ids->mnt_ns_id, &mnt_ns_desc);
+	if (ns == NULL)
+		return -1;
+
+	if (mntns_collect_root(ns->pid) < 0)
+		return -1;
+
 	d = xzalloc(sizeof(*d));
 	if (!d)
 		return -1;
@@ -432,7 +442,8 @@ static int unix_collect_one(const struct unix_diag_msg *m,
 						name, m->udiag_ino);
 				drop_path = true;
 			} else if ((st.st_ino != uv->udiag_vfs_ino) ||
-			    !phys_stat_dev_match(st.st_dev, uv->udiag_vfs_dev, name)) {
+			    !phys_stat_dev_match(ns->mnt.mntinfo_tree, st.st_dev,
+							uv->udiag_vfs_dev, name)) {
 				pr_info("unix: Dropping path %s for "
 						"unlinked bound "
 						"sk %#x.%#x real %#x.%#x\n",
-- 
1.8.5.3



More information about the CRIU mailing list