[CRIU] Re: [PATCH 4/6] tty: No need to test unpaired slaves if --ext-tty passed

Cyrill Gorcunov gorcunov at openvz.org
Wed Sep 26 11:56:32 EDT 2012


On Wed, Sep 26, 2012 at 05:05:45PM +0400, Cyrill Gorcunov wrote:
> In case if --ext-tty passed we're informed that we should
> restore any external slave tty we've met.
> 

OK, so instead of patches 4-6, please review this one as a substitute.

-------------- next part --------------
>From 259929e392193265669f578a0b74be50ab7a3240 Mon Sep 17 00:00:00 2001
From: Cyrill Gorcunov <gorcunov at openvz.org>
Date: Wed, 19 Sep 2012 19:18:27 +0400
Subject: [PATCH] tty: Migrate tty slave peer connections

In case if we've dumped a slave peer only (say a user dumped
`top' application) we should migrate it on current active
terminal.

Note only one external slave peer is allowed simply
because otherwise we can't distinguish which indices
should be used for each of them.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 cr-dump.c     |    2 +-
 include/tty.h |    2 +-
 tty.c         |  107 ++++++++++++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 93 insertions(+), 18 deletions(-)

diff --git a/cr-dump.c b/cr-dump.c
index 0541e5c..c347780 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -1630,7 +1630,7 @@ int cr_dump_tasks(pid_t pid, const struct cr_options *opts)
 	if (ret)
 		goto err;
 
-	ret = tty_verify_active_pairs();
+	ret = tty_verify_active_pairs(opts->ext_tty);
 	if (ret)
 		goto err;
 
diff --git a/include/tty.h b/include/tty.h
index eccc3f2..6a7110b 100644
--- a/include/tty.h
+++ b/include/tty.h
@@ -18,6 +18,6 @@ extern int collect_tty(void);
 extern int prepare_shared_tty(void);
 extern void tty_setup_slavery(void);
 
-extern int tty_verify_active_pairs(void);
+extern int tty_verify_active_pairs(bool ext_tty);
 
 #endif /* CR_TTY_H__ */
diff --git a/tty.c b/tty.c
index ee63273..6394150 100644
--- a/tty.c
+++ b/tty.c
@@ -144,11 +144,11 @@ static int tty_get_index(u32 id)
 }
 
 /* Make sure the active pairs do exist */
-int tty_verify_active_pairs(void)
+int tty_verify_active_pairs(bool ext_tty)
 {
-	unsigned long i;
+	unsigned long i, j;
 
-	for (i = 0; i < sizeof(tty_active_pairs); i++) {
+	for (i = j = 0; i < sizeof(tty_active_pairs); i++) {
 		i = find_next_bit(tty_active_pairs,
 				  sizeof(tty_active_pairs), i);
 
@@ -161,10 +161,18 @@ int tty_verify_active_pairs(void)
 				continue;
 			}
 
-			pr_err("Found slave peer index %d without "
-				"correspond master peer\n",
-				tty_get_index(i));
-			return -1;
+			if (!ext_tty) {
+				pr_err("Found slave peer index %d without "
+				       "correspond master peer\n",
+				       tty_get_index(i));
+				return -1;
+			}
+
+			if (j++ >= 1) {
+				pr_err("Only one slave external peer "
+				       "is allowed\n");
+				return -1;
+			}
 		}
 	}
 
@@ -539,21 +547,69 @@ static int receive_tty(struct tty_info *info)
 	return fd;
 }
 
-static int pty_open_fake_ptmx(struct tty_info *slave)
+static int pty_get_current_pts_index(pid_t pid)
+{
+	struct proc_pid_stat s;
+	int pfd, major, minor, ret;
+
+	pfd = open_pid_proc(pid);
+	if (pfd < 0)
+		return -1;
+
+	ret = parse_pid_stat(pid, &s);
+	close_pid_proc();
+
+	if (ret)
+		return -1;
+
+	major = (s.tty_nr & 0xfff00) >> 8;
+	minor = (s.tty_nr & 0xff) | ((s.tty_nr >> 12) & 0xfff00);
+
+	if (major != UNIX98_PTY_SLAVE_MAJOR) {
+		pr_err("Major number mismatch, %d expected but got %d\n",
+			UNIX98_PTY_SLAVE_MAJOR, major);
+		return -1;
+	}
+
+	return minor;
+}
+
+static int pty_open_unpaired_slave(struct tty_info *slave)
 {
 	int master = -1, ret = -1, fd = -1;
 	char pts_name[64];
 
-	snprintf(pts_name, sizeof(pts_name), PTS_FMT, slave->tie->pty->index);
+	/*
+	 * We may have 2 cases here:
+	 *
+	 *  - @termios present thus it's external slave peer
+	 *    which should be migrated on current pts
+	 *
+	 *  - no @termios means the peer is dead so we need
+	 *    a fake master peer
+	 */
 
-	master = pty_open_ptmx_index(O_RDONLY, slave->tie->pty->index);
-	if (master < 0) {
-		pr_perror("Can't open fale %x (index %d)",
-			  slave->tfe->id, slave->tie->pty->index);
-		return -1;
+	if (likely(slave->tie->termios)) {
+		int index = pty_get_current_pts_index(getpid());
+		if (index < 0)
+			goto err;
+
+		pr_info("Migrated slave peer indices %d -> %d\n",
+			slave->tie->pty->index, index);
+
+		slave->tie->pty->index = index;
+	} else {
+		master = pty_open_ptmx_index(O_RDONLY, slave->tie->pty->index);
+		if (master < 0) {
+			pr_perror("Can't open fale %x (index %d)",
+				  slave->tfe->id, slave->tie->pty->index);
+			return -1;
+		}
+
+		unlock_pty(master);
 	}
 
-	unlock_pty(master);
+	snprintf(pts_name, sizeof(pts_name), PTS_FMT, slave->tie->pty->index);
 
 	fd = open(pts_name, slave->tfe->flags);
 	if (fd < 0) {
@@ -564,6 +620,15 @@ static int pty_open_fake_ptmx(struct tty_info *slave)
 	if (restore_tty_params(fd, slave))
 		goto err;
 
+	/*
+	 * If tty is migrated we need to restore its group
+	 * as well, otherwise key press won't be handled.
+	 */
+	if (likely(slave->tie->termios)) {
+		if (tty_set_prgp(fd, getpgrp()))
+			goto err;
+	}
+
 	if (pty_open_slaves(slave))
 		goto err;
 
@@ -626,7 +691,7 @@ static int tty_open(struct file_desc *d)
 		return receive_tty(info);
 
 	if (!pty_is_master(info))
-		return pty_open_fake_ptmx(info);
+		return pty_open_unpaired_slave(info);
 
 	return pty_open_ptmx(info);
 
@@ -856,6 +921,8 @@ static int collect_one_tty(void *obj, ProtobufCMessage *msg)
 	if (verify_info(info))
 		return -1;
 
+	tty_test_and_set(info->tie->id, tty_active_pairs);
+
 	pr_info("Collected tty ID %#x\n", info->tfe->id);
 
 	list_add(&info->list, &all_ttys);
@@ -875,6 +942,14 @@ int collect_tty(void)
 		ret = collect_image(CR_FD_TTY, PB_TTY,
 				sizeof(struct tty_info),
 				collect_one_tty);
+
+	/*
+	 * Make sure only one external tty present which
+	 * can be migrated.
+	 */
+	if (!ret)
+		ret = tty_verify_active_pairs(true);
+
 	return ret;
 }
 
-- 
1.7.7.6



More information about the CRIU mailing list