[CRIU] [PATCH 1/5] mount: save the result of mnt_is_overmounted

Pavel Tikhomirov ptikhomirov at virtuozzo.com
Mon Sep 17 14:47:53 MSK 2018


On restore we change mounts tree topology and paths in find_remap_mounts
thus mns_is_overmounted does not account remaped overmounts. So to know
which mounts will be actually overmounted after restore we need two much
effort, better prepare these info in advance.

That also should improve performance of mnt_is_overmounted on dump,
as we reuse calculations from previous calls.

Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
 criu/include/mount.h |  2 ++
 criu/mount.c         | 36 ++++++++++++++++++++++++++++++------
 2 files changed, 32 insertions(+), 6 deletions(-)

diff --git a/criu/include/mount.h b/criu/include/mount.h
index ca17b059a..e7d026264 100644
--- a/criu/include/mount.h
+++ b/criu/include/mount.h
@@ -70,6 +70,8 @@ struct mount_info {
 
 	struct list_head	postpone;
 
+	int			is_overmounted;
+
 	void			*private;	/* associated filesystem data */
 };
 
diff --git a/criu/mount.c b/criu/mount.c
index bdc39b530..ba202f0c9 100644
--- a/criu/mount.c
+++ b/criu/mount.c
@@ -1152,17 +1152,29 @@ static int get_clean_fd(struct mount_info *mi)
  * root of our mount namespace as it is covered by other mount.
  * mnt_is_overmounted() checks if mount is not visible.
  */
-static bool mnt_is_overmounted(struct mount_info *mi)
+static int mnt_is_overmounted(struct mount_info *mi)
 {
 	struct mount_info *t, *c, *m = mi;
 
+	if (mi->is_overmounted != -1)
+		goto exit;
+
+	mi->is_overmounted = 0;
+
 	while (m->parent) {
+		if (mi->parent->is_overmounted == 1) {
+			mi->is_overmounted = 1;
+			goto exit;
+		}
+
 		/* Check there is no sibling-overmount */
 		list_for_each_entry(t, &m->parent->children, siblings) {
 			if (m == t)
 				continue;
-			if (issubpath(m->mountpoint, t->mountpoint))
-				return true;
+			if (issubpath(m->mountpoint, t->mountpoint)) {
+				mi->is_overmounted = 1;
+				goto exit;
+			}
 		}
 
 		/*
@@ -1175,10 +1187,19 @@ static bool mnt_is_overmounted(struct mount_info *mi)
 
 	/* Check there is no children-overmount */
 	list_for_each_entry(c, &mi->children, siblings)
-		if (!strcmp(c->mountpoint, mi->mountpoint))
-			return true;
+		if (!strcmp(c->mountpoint, mi->mountpoint)) {
+			mi->is_overmounted = 1;
+			goto exit;
+		}
 
-	return false;
+exit:
+	return mi->is_overmounted;
+}
+
+static int set_is_overmounted(struct mount_info *mi)
+{
+	mnt_is_overmounted(mi);
+	return 0;
 }
 
 /*
@@ -2723,6 +2744,7 @@ struct mount_info *mnt_entry_alloc()
 	new = xzalloc(sizeof(struct mount_info));
 	if (new) {
 		new->fd = -1;
+		new->is_overmounted = -1;
 		INIT_LIST_HEAD(&new->children);
 		INIT_LIST_HEAD(&new->siblings);
 		INIT_LIST_HEAD(&new->mnt_slave_list);
@@ -3160,6 +3182,8 @@ static int populate_mnt_ns(void)
 	if (validate_mounts(mntinfo, false))
 		return -1;
 
+	mnt_tree_for_each(pms, set_is_overmounted);
+
 	if (find_remap_mounts(pms))
 		return -1;
 
-- 
2.17.1



More information about the CRIU mailing list