[CRIU] [PATCH] mnt: Carry run-time device ID in mount_info

Cyrill Gorcunov gorcunov at openvz.org
Wed Dec 2 07:57:34 PST 2015


When we're restoring fsnotify watchees we need to resolve
path to a handle at some mountpoint referred by @s_dev
member (device ID) which is saved inside image. This
ID actually may be changed at the every mount (say
one restores container after machine reboot) or in
case of container's migration.

Thus the test for overmounting in __open_mountpoint
will fail and we get an error.

Lets do a trick: introduce @s_dev_rt member which
is supposed to carry run-time device ID. When dumping
this member simply equal to traditional @s_dev fetched
from the procfs, but when restoring we fetch it from
stat call once mountpoint become alive.

https://jira.sw.ru/browse/PSBM-41610

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---

Guys, take a look please.

 include/mount.h |  1 +
 mount.c         | 27 ++++++++++++++++++++++++---
 proc_parse.c    |  2 +-
 3 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/include/mount.h b/include/mount.h
index c3abc8479965..6831adf84910 100644
--- a/include/mount.h
+++ b/include/mount.h
@@ -33,6 +33,7 @@ struct mount_info {
 	int			mnt_id;
 	int			parent_mnt_id;
 	unsigned int		s_dev;
+	unsigned int		s_dev_rt;
 	char			*root;
 	/*
 	 * During dump mountpoint contains path with dot at the
diff --git a/mount.c b/mount.c
index 25fbc134ebe1..253025cb4971 100644
--- a/mount.c
+++ b/mount.c
@@ -1009,9 +1009,18 @@ int __open_mountpoint(struct mount_info *pm, int mnt_fd)
 	}
 
 	dev = phys_stat_resolve_dev(pm->nsid, st.st_dev, pm->ns_mountpoint + 1);
-	if (dev != pm->s_dev) {
-		pr_err("The file system %#x (%#x) %s %s is inaccessible\n",
-		       pm->s_dev, (int)dev, pm->fstype->name, pm->ns_mountpoint);
+	/*
+	 * To prevent overmount clash we use two entries
+	 * @s_dev and @s_dev_rt.  On dump @s_dev = @s_dev_rt
+	 * obtained from procfs parsing but on restore @s_dev_rt
+	 * may differ with one obtained from the image: the device
+	 * ID may be new on provided by the kernel itself on new
+	 * mount.
+	 */
+	if (dev != pm->s_dev && dev != pm->s_dev_rt) {
+		pr_err("The file system %#x %#x (%#x) %s %s is inaccessible\n",
+		       pm->s_dev, pm->s_dev_rt, (int)dev,
+		       pm->fstype->name, pm->ns_mountpoint);
 		goto err;
 	}
 
@@ -1795,9 +1804,21 @@ static char *resolve_source(struct mount_info *mi)
 
 static int restore_shared_options(struct mount_info *mi, bool private, bool shared, bool slave)
 {
+	struct stat st;
+
 	pr_debug("%d:%s private %d shared %d slave %d\n",
 			mi->mnt_id, mi->mountpoint, private, shared, slave);
 
+	/*
+	 * Fetch runtime device once we're mounted for mount
+	 * resolving when device has been migrated.
+	 */
+	if (stat(mi->mountpoint, &st)) {
+		pr_perror("Can't stat on %s\n", mi->mountpoint);
+		return -1;
+	}
+	mi->s_dev_rt = MKKDEV(major(st.st_dev), minor(st.st_dev));
+
 	if (mi->flags & MS_UNBINDABLE) {
 		if (shared || slave)
 			pr_warn("%s has both unbindable and sharing, ignoring unbindable\n", mi->mountpoint);
diff --git a/proc_parse.c b/proc_parse.c
index 3d924b2f68d5..4d67a13188bd 100644
--- a/proc_parse.c
+++ b/proc_parse.c
@@ -1041,7 +1041,7 @@ static int parse_mountinfo_ent(char *str, struct mount_info *new, char **fsname)
 	if (!new->mountpoint)
 		goto err;
 
-	new->s_dev = MKKDEV(kmaj, kmin);
+	new->s_dev = new->s_dev_rt = MKKDEV(kmaj, kmin);
 	new->flags = 0;
 	if (parse_mnt_flags(opt, &new->flags))
 		goto err;
-- 
2.5.0



More information about the CRIU mailing list