[CRIU] [PATCH 4/7] tty: mount -- Add mount_resolve_devpts_mnt_id helper

Cyrill Gorcunov gorcunov at openvz.org
Thu Jan 19 14:15:58 PST 2017


We will need it to distinguish multiple devpts mounted.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 criu/include/mount.h |  1 +
 criu/mount.c         | 40 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+)

diff --git a/criu/include/mount.h b/criu/include/mount.h
index a692b550bb91..62ad2676880d 100644
--- a/criu/include/mount.h
+++ b/criu/include/mount.h
@@ -102,6 +102,7 @@ extern struct mount_info *lookup_mnt_sdev(unsigned int s_dev);
 extern dev_t phys_stat_resolve_dev(struct ns_id *, dev_t st_dev, const char *path);
 extern bool phys_stat_dev_match(dev_t st_dev, dev_t phys_dev,
 				struct ns_id *, const char *path);
+extern int mount_resolve_devpts_mnt_id(int s_dev);
 
 extern int restore_task_mnt_ns(struct pstree_item *current);
 extern void fini_restore_mntns(void);
diff --git a/criu/mount.c b/criu/mount.c
index 4749f59d4628..fb6825b38fa9 100644
--- a/criu/mount.c
+++ b/criu/mount.c
@@ -263,6 +263,46 @@ static struct mount_info *mount_resolve_path(struct mount_info *mntinfo_tree, co
 	return m;
 }
 
+/*
+ * Figuring out mount id is a bit tricky for PTYs: when
+ * several devpts mounted they have own superblocks
+ * thus opening /dev/<dirs>/ptmx leads to slave
+ * peers lay into /dev/<dirs>/0 and etc, but the
+ * exception is toplevel /dev/ptmx, when opened the
+ * kernel lookups for first "pts" downlevel directory mounted
+ * at /dev/pts (which of course must have DEVPTS_SUPER_MAGIC
+ * in properties). It's done for backward compatibility,
+ * see drivers/tty/pty.c:ptmx_open.
+ */
+int mount_resolve_devpts_mnt_id(int s_dev)
+{
+	struct mount_info *mi;
+
+	mi = lookup_mnt_sdev(s_dev);
+	if (!mi) {
+		pr_err("No devpts mount point found for s_dev %#x\n", s_dev);
+		return -1;
+	}
+
+	if (mi->fstype->code == FSTYPE__DEVPTS) {
+		return mi->mnt_id;
+	} else if (mi->fstype->code == FSTYPE__DEVTMPFS) {
+		char path[PATH_MAX];
+
+		snprintf(path, sizeof(path), "%s/pts", mi->mountpoint + 1);
+		mi = mount_resolve_path(mi, path);
+		if (!mi) {
+			pr_err("Can't resolve %s\n", path);
+			return -1;
+		}
+		if (mi->fstype->code == FSTYPE__DEVPTS)
+			return mi->mnt_id;
+	}
+
+	pr_err("Can't resolve devpts for s_dev %#x\n", s_dev);
+	return -1;
+}
+
 dev_t phys_stat_resolve_dev(struct ns_id *ns, dev_t st_dev, const char *path)
 {
 	struct mount_info *m;
-- 
2.7.4



More information about the CRIU mailing list