[CRIU] [PATCH 5/5] tty: Migrate tty slave peer connection

Cyrill Gorcunov gorcunov at openvz.org
Thu Sep 27 08:17:42 EDT 2012


In case if we've dumped a slave peer only (say a user dumped
`top' application) we should migrate it on current active
terminal, which barely an own standart stream prepared for us
by file engine.

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         |   89 +++++++++++++++++++++++++++++++++++++++++++--------------
 3 files changed, 69 insertions(+), 24 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 cb860b1..a106479 100644
--- a/include/tty.h
+++ b/include/tty.h
@@ -18,7 +18,7 @@ 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);
 
 extern int tty_prep_fds(void);
 extern void tty_fini_fds(void);
diff --git a/tty.c b/tty.c
index acb89bc..68c47d2 100644
--- a/tty.c
+++ b/tty.c
@@ -145,11 +145,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);
 
@@ -162,10 +162,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;
+			}
 		}
 	}
 
@@ -540,31 +548,58 @@ static int receive_tty(struct tty_info *info)
 	return fd;
 }
 
-static int pty_open_fake_ptmx(struct tty_info *slave)
+static int pty_open_unpaired_slave(struct file_desc *d, 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
+	 */
+
+	if (likely(slave->tie->termios)) {
+		fd = get_service_fd(SELF_STDIN_OFF);
+		pr_info("Migrated slave peer %x -> to fd %d\n",
+			slave->tfe->id, fd);
+	} else {
+		char pts_name[64];
 
-	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;
-	}
+		snprintf(pts_name, sizeof(pts_name), PTS_FMT, slave->tie->pty->index);
 
-	unlock_pty(master);
+		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);
+
+		fd = open(pts_name, slave->tfe->flags);
+		if (fd < 0) {
+			pr_perror("Can't open slave %s", pts_name);
+			goto err;
+		}
 
-	fd = open(pts_name, slave->tfe->flags);
-	if (fd < 0) {
-		pr_perror("Can't open slave %s", pts_name);
-		goto err;
 	}
 
 	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;
 
@@ -627,7 +662,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(d, info);
 
 	return pty_open_ptmx(info);
 
@@ -857,6 +892,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);
@@ -876,6 +913,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