[2/7] tty: mount -- Add mount_resolve_devpts_mnt_id helper

Submitted by Cyrill Gorcunov on Feb. 2, 2017, 8:02 a.m.

Details

Message ID 1486022529-1901-3-git-send-email-gorcunov@openvz.org
State New
Series "tty: Add support for multiple devpts instances"
Headers show

Commit Message

Cyrill Gorcunov Feb. 2, 2017, 8:02 a.m.
We will need it to distinguish multiple devpts mounted.

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

Patch hide | download patch | download mbox

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 4ba6cc27e9eb..69d8fbd764ef 100644
--- a/criu/mount.c
+++ b/criu/mount.c
@@ -234,6 +234,20 @@  struct mount_info *lookup_mnt_sdev(unsigned int s_dev)
 	return NULL;
 }
 
+/* Lookup for sdev skipping bind mounts */
+static struct mount_info *lookup_mnt_sdev_on_root(unsigned int s_dev)
+{
+	struct mount_info *m;
+
+	for (m = mntinfo; m; m = m->next) {
+		if (m->s_dev == s_dev &&
+		    is_root(m->root))
+			return m;
+	}
+
+	return NULL;
+}
+
 static struct mount_info *mount_resolve_path(struct mount_info *mntinfo_tree, const char *path)
 {
 	size_t pathlen = strlen(path);
@@ -263,6 +277,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_on_root(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/ptmx", mi->ns_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;