[CRIU] [RFC] tty: Use mountpoit reference instead of hardcoded paths

Cyrill Gorcunov gorcunov at openvz.org
Thu Oct 2 05:06:22 PDT 2014


Previously we use "/dev/pts" as predefinde canonical path for pty slave
peers. This is fine for most of configurations but same time the kernel
doesn't care where devpts is mounted and rather only interested in device
numbers which are mapped to chanracter regions.

Thus lets do more flexible way -- add @mnt_id into pty images, thus on
restore we will simply figure out where devpts mount point is laying
and inspect ptys there.

Still for pty master device we refer to hardcoded /dev/ptmx path.
It might be worth to add more validations here.

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

Note this patch is on top of preparatory tty series I've sent tonight.

 protobuf/tty.proto |  1 +
 tty.c              | 95 ++++++++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 79 insertions(+), 17 deletions(-)

diff --git a/protobuf/tty.proto b/protobuf/tty.proto
index 8942965c580b..215bff35f212 100644
--- a/protobuf/tty.proto
+++ b/protobuf/tty.proto
@@ -21,6 +21,7 @@ message termios_entry {
 
 message tty_pty_entry {
 	required uint32			index		= 1;
+	optional uint32			mnt_id		= 2;
 }
 
 enum TtyType {
diff --git a/tty.c b/tty.c
index 89e3d57f5f48..c9aa70bc4087 100644
--- a/tty.c
+++ b/tty.c
@@ -22,6 +22,7 @@
 #include "servicefd.h"
 #include "image.h"
 #include "util.h"
+#include "mount.h"
 #include "log.h"
 #include "list.h"
 #include "util-pie.h"
@@ -201,7 +202,7 @@ int tty_verify_active_pairs(void)
 	return 0;
 }
 
-static int parse_pty_index(u32 id, int lfd, int major)
+static int parse_pty_index(u32 id, const struct fd_parms *p, struct mount_info *m, int lfd, int major)
 {
 	int index = -1;
 
@@ -214,9 +215,9 @@ static int parse_pty_index(u32 id, int lfd, int major)
 		break;
 
 	case UNIX98_PTY_SLAVE_MAJOR: {
-		char path[PATH_MAX];
-		char link[32];
+		char path[PATH_MAX], fmt[PATH_MAX];
 		int len;
+		char link[32];
 
 		snprintf(link, sizeof(link), "/proc/self/fd/%d", lfd);
 		len = readlink(link, path, sizeof(path) - 1);
@@ -226,10 +227,14 @@ static int parse_pty_index(u32 id, int lfd, int major)
 		}
 		path[len] = '\0';
 
-		if (sscanf(path, PTS_FMT, &index) != 1) {
-			pr_err("Unexpected format on path %s\n", path);
+		snprintf(fmt, sizeof(fmt), "%s/%s", m->mountpoint + 1, "%d");
+
+		if (sscanf(path, fmt, &index) != 1) {
+			pr_err("Unexpected path (%s) on format (%s)\n", path, fmt);
 			return -1;
 		}
+		pr_debug("pty slave peer %#x on %s/%d (mnt_id %#x s_dev %#x)\n",
+			 id, m->mountpoint + 1, index, m->mnt_id, m->s_dev);
 		break;
 	}
 	}
@@ -350,16 +355,52 @@ static int tty_set_prgp(int fd, int group)
 	return 0;
 }
 
+static int tty_gen_open_path(struct tty_info *info, char *path, size_t size)
+{
+	TtyPtyEntry *pty = info->tie->pty;
+
+	/*
+	 * In new format we keep mount point reference
+	 * on the dump but old versions still may use
+	 * predefined path :-(
+	 */
+	if (likely(pty->has_mnt_id)) {
+		struct mount_info *m;
+
+		m = lookup_mnt_id(pty->mnt_id);
+		if (!m) {
+			pr_err("Can't find mount point for %x\n",
+			       info->tfe->id);
+			return -1;
+		}
+		snprintf(path, size, "%s/%d", m->mountpoint + 1, pty->index);
+	} else
+		snprintf(path, size, PTS_FMT, pty->index);
+	pr_debug("pty %#x path resolved to %s\n", info->tfe->id, path);
+
+	return 0;
+}
+
 static int tty_restore_ctl_terminal(struct file_desc *d, int fd)
 {
 	struct tty_info *info = container_of(d, struct tty_info, d);
 	int slave, ret = -1;
-	char pts_name[64];
+	char pts_name[PATH_MAX];
 
 	if (!is_service_fd(fd, CTL_TTY_OFF))
 		return 0;
 
-	snprintf(pts_name, sizeof(pts_name), PTS_FMT, info->tie->pty->index);
+	if (likely(!list_empty(&info->sibling))) {
+		if (tty_gen_open_path(list_first_entry(&info->sibling,
+						       struct tty_info,
+						       sibling),
+				      pts_name, sizeof(pts_name)))
+			return -1;
+	} else {
+		snprintf(pts_name, sizeof(pts_name), PTS_FMT, info->tie->pty->index);
+		pr_warn_once("Restoring control terminal via %s\n", pts_name);
+	}
+
 	slave = open(pts_name, O_RDONLY);
 	if (slave < 0) {
 		pr_perror("Can't open %s", pts_name);
@@ -465,9 +506,7 @@ static int pty_open_slaves(struct tty_info *info)
 	int sock = -1, fd = -1, ret = -1;
 	struct fdinfo_list_entry *fle;
 	struct tty_info *slave;
-	char pts_name[64];
-
-	snprintf(pts_name, sizeof(pts_name), PTS_FMT, info->tie->pty->index);
+	char pts_name[PATH_MAX];
 
 	sock = socket(PF_UNIX, SOCK_DGRAM, 0);
 	if (sock < 0) {
@@ -478,6 +517,9 @@ static int pty_open_slaves(struct tty_info *info)
 	list_for_each_entry(slave, &info->sibling, sibling) {
 		BUG_ON(tty_is_master(slave));
 
+		if (tty_gen_open_path(slave, pts_name, sizeof(pts_name)))
+			return -1;
+
 		fd = open(pts_name, slave->tfe->flags | O_NOCTTY);
 		if (fd < 0) {
 			pr_perror("Can't open slave %s", pts_name);
@@ -547,10 +589,10 @@ static int pty_open_unpaired_slave(struct file_desc *d, struct tty_info *slave)
 		pr_info("Migrated slave peer %x -> to fd %d\n",
 			slave->tfe->id, fd);
 	} else {
-		char pts_name[64];
-
-		snprintf(pts_name, sizeof(pts_name), PTS_FMT, slave->tie->pty->index);
+		char pts_name[PATH_MAX];
 
+		if (tty_gen_open_path(slave, pts_name, sizeof(pts_name)))
+			return -1;
 		master = pty_open_ptmx_index(O_RDONLY, slave->tie->pty->index);
 		if (master < 0) {
 			pr_perror("Can't open fale %x (index %d)",
@@ -562,7 +604,8 @@ static int pty_open_unpaired_slave(struct file_desc *d, struct tty_info *slave)
 
 		fd = open(pts_name, slave->tfe->flags | O_NOCTTY);
 		if (fd < 0) {
-			pr_perror("Can't open slave %s", pts_name);
+			pr_perror("Can't open slave %s for fd %d",
+				  pts_name, fd);
 			goto err;
 		}
 
@@ -1056,7 +1099,7 @@ int dump_verify_tty_sids(void)
 	return ret;
 }
 
-static int dump_pty_info(int lfd, u32 id, const struct fd_parms *p, int major, int minor, int index)
+static int dump_pty_info(int lfd, u32 id, const struct fd_parms *p, const struct mount_info *m, int major, int minor, int index)
 {
 	TtyInfoEntry info		= TTY_INFO_ENTRY__INIT;
 	TermiosEntry termios		= TERMIOS_ENTRY__INIT;
@@ -1108,6 +1151,8 @@ static int dump_pty_info(int lfd, u32 id, const struct fd_parms *p, int major, i
 	info.packet_mode	= pti->st_pckt;
 
 	pty.index		= index;
+	pty.has_mnt_id		= true;
+	pty.mnt_id		= m->mnt_id;
 
 	/*
 	 * Nothing we can do on hanging up terminal,
@@ -1170,9 +1215,25 @@ out:
 static int dump_one_pty(int lfd, u32 id, const struct fd_parms *p, int major, int minor)
 {
 	TtyFileEntry e = TTY_FILE_ENTRY__INIT;
+	struct mount_info *m;
 	int ret = 0, index;
 
-	index = parse_pty_index(id, lfd, major);
+	/*
+	 * Slave peers are sitting as /@path/%d, where
+	 * @path is mountpoint for devpts filesystem.
+	 * See devpts_pty_new() kernel's helper.
+	 */
+	if (p->mnt_id != -1)
+		m = lookup_mnt_id(p->mnt_id);
+	else
+		m = lookup_mnt_sdev(p->stat.st_dev);
+
+	if (!m) {
+		pr_err("Can't resolve mount point for tty %x\n", id);
+		return -1;
+	}
+
+	index = parse_pty_index(id, p, m, lfd, major);
 	if (index < 0)
 		return -1;
 
@@ -1202,7 +1263,7 @@ static int dump_one_pty(int lfd, u32 id, const struct fd_parms *p, int major, in
 	 */
 
 	if (!tty_test_and_set(e.tty_info_id, tty_bitmap))
-		ret = dump_pty_info(lfd, e.tty_info_id, p, major, minor, index);
+		ret = dump_pty_info(lfd, e.tty_info_id, p, m, major, minor, index);
 
 	if (!ret)
 		ret = pb_write_one(img_from_set(glob_imgset, CR_FD_TTY_FILES), &e, PB_TTY_FILE);
-- 
1.9.3



More information about the CRIU mailing list