tty: Use mnt_id for first lookup of toplevel devpts

Submitted by Cyrill Gorcunov on Nov. 30, 2017, 7:34 p.m.

Details

Message ID 1512070478-23127-1-git-send-email-gorcunov@virtuozzo.com
State New
Series "tty: Use mnt_id for first lookup of toplevel devpts"
Headers show

Commit Message

Cyrill Gorcunov Nov. 30, 2017, 7:34 p.m.
When we're searching for toplevel devpts mount into which
the toplevel /dev/ptmx device is pointing to we should use
mnt_id from mountinfo first, this is most reliable way to
detect mounting.

But on old kernels mnt_id may not be present so we should
try s_dev lookup then and here is a nit -- mointinfo keeps
superblock device in kernel format while the source s_dev
is obtained from the stat() syscall so we should use
kdev_to_odev helper to not miss device if there are many
devpts mounted on the node.

Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
---
 criu/include/mount.h |  2 +-
 criu/mount.c         | 20 +++++++++++++-------
 criu/tty.c           |  2 +-
 3 files changed, 15 insertions(+), 9 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/include/mount.h b/criu/include/mount.h
index e19f767..0d47d0f 100644
--- a/criu/include/mount.h
+++ b/criu/include/mount.h
@@ -105,7 +105,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 mount_resolve_devpts_mnt_id(int mnt_id, int s_dev);
 extern struct mount_info *lookup_first_fstype(int code);
 
 extern int restore_task_mnt_ns(struct pstree_item *current);
diff --git a/criu/mount.c b/criu/mount.c
index ba3d60d..5e645aa 100644
--- a/criu/mount.c
+++ b/criu/mount.c
@@ -245,10 +245,11 @@  static struct mount_info *lookup_mnt_sdev_on_root(unsigned int s_dev)
 {
 	struct mount_info *m;
 
-	for (m = mntinfo; m != NULL; m = m->next)
-		if (m->s_dev == s_dev &&
+	for (m = mntinfo; m != NULL; m = m->next) {
+		if (kdev_to_odev(m->s_dev) == s_dev &&
 		    is_root(m->root))
 			return m;
+	}
 
 	return NULL;
 }
@@ -293,14 +294,19 @@  static struct mount_info *mount_resolve_path(struct mount_info *mntinfo_tree, co
  * in properties). It's done for backward compatibility,
  * see drivers/tty/pty.c:ptmx_open.
  */
-int mount_resolve_devpts_mnt_id(int s_dev)
+int mount_resolve_devpts_mnt_id(int mnt_id, int s_dev)
 {
-	struct mount_info *mi;
+	struct mount_info *mi = NULL;
+
+	if (mnt_id != -1)
+		mi = lookup_mnt_id(mnt_id);
 
-	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;
+		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) {
diff --git a/criu/tty.c b/criu/tty.c
index 10b489f..1eb239b 100644
--- a/criu/tty.c
+++ b/criu/tty.c
@@ -2042,7 +2042,7 @@  static int dump_one_tty(int lfd, u32 id, const struct fd_parms *p)
 	e.fown		= (FownEntry *)&p->fown;
 
 	if (is_pty(driver)) {
-		mnt_id = mount_resolve_devpts_mnt_id(p->stat.st_dev);
+		mnt_id = mount_resolve_devpts_mnt_id(p->mnt_id, p->stat.st_dev);
 		if (mnt_id < 0) {
 			pr_info("Can't obtain mnt_id on tty %d id %#x\n", lfd, id);
 			return -1;