[1/9] mount: add helper to check unsupported children collision

Submitted by Pavel Tikhomirov on July 10, 2018, 4:02 p.m.

Details

Message ID 20180710160231.1292-2-ptikhomirov@virtuozzo.com
State Accepted
Series "mount: better handling of mount propagation"
Commit 4538b44b906cc5cc25bcaad50493fd7dbb34d2ba
Headers show

Commit Message

Pavel Tikhomirov July 10, 2018, 4:02 p.m.
See more detailed explanation inside in-code comment.

note: Actually before we remove validate_mounts (later in these
patchset) we likely won't get to these check and fail earlier, as having
children collision implies shared mounts with different sets of
children.

note: from v4.11 and ms kernel commit 1064f874abc0 ("mnt: Tuck mounts
under others instead of creating shadow/side mounts.") there will be no
more mount collision.

Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
---
 criu/mount.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

Patch hide | download patch | download mbox

diff --git a/criu/mount.c b/criu/mount.c
index 47c65d510..2d3752b20 100644
--- a/criu/mount.c
+++ b/criu/mount.c
@@ -685,6 +685,34 @@  static bool mnt_is_external(struct mount_info *m)
 	return 0;
 }
 
+/*
+ * Having two children whith same mountpoint is unsupported. That can happen in
+ * case of mount propagation inside of shared mounts, in that case it is hard
+ * to find out mount propagation siblings and which of these mounts is above
+ * (visible) and which is beneath (hidden). It would've broken mount restore
+ * order in can_mount_now and also visibility assumptions in open_mountpoint.
+ *
+ * Anyway after kernel v4.11 such mounts will be impossible.
+ */
+static int validate_children_collision(struct mount_info *mnt)
+{
+	struct mount_info *chi, *chj;
+
+	list_for_each_entry(chi, &mnt->children, siblings) {
+		list_for_each_entry(chj, &mnt->children, siblings) {
+			if (chj == chi)
+				break;
+			if (!strcmp(chj->mountpoint, chi->mountpoint)) {
+				pr_err("Mount %d has two children with same "
+				       "mountpoint: %d %d\n",
+				       mnt->mnt_id, chj->mnt_id, chi->mnt_id);
+				return -1;
+			}
+		}
+	}
+	return 0;
+}
+
 static int validate_mounts(struct mount_info *info, bool for_dump)
 {
 	struct mount_info *m, *t;
@@ -697,6 +725,9 @@  static int validate_mounts(struct mount_info *info, bool for_dump)
 		if (m->shared_id && validate_shared(m))
 			return -1;
 
+		if (validate_children_collision(m))
+			return -1;
+
 		if (mnt_is_external(m))
 			continue;