[CRIU] [PATCH 4/6] tty: Implement support of current tty

Cyrill Gorcunov gorcunov at openvz.org
Thu Mar 19 08:13:11 PDT 2015


Opening current tty is tricky: first slave peer should
be opened and session restored, and only then we can
open /dev/tty. So that I made rst_info to carry
additional list @tty_ctty where all current ttys
get gathered and opened after slave peers were
brought to live.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 files.c            | 16 ++++++++++++++++
 include/rst_info.h |  1 +
 protobuf/tty.proto |  1 +
 tty.c              | 32 +++++++++++++++++++++++++++++---
 4 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/files.c b/files.c
index acd5735144a3..351a4868d1e9 100644
--- a/files.c
+++ b/files.c
@@ -607,6 +607,7 @@ int prepare_fd_pid(struct pstree_item *item)
 	INIT_LIST_HEAD(&rst_info->fds);
 	INIT_LIST_HEAD(&rst_info->eventpoll);
 	INIT_LIST_HEAD(&rst_info->tty_slaves);
+	INIT_LIST_HEAD(&rst_info->tty_ctty);
 
 	if (!fdinfo_per_id) {
 		img = open_image(CR_FD_FDINFO, O_RSTR, pid);
@@ -1022,6 +1023,21 @@ int prepare_fds(struct pstree_item *me)
 			break;
 	}
 
+	for (state = 0; state < ARRAY_SIZE(states); state++) {
+		if (!states[state].required) {
+			pr_debug("Skipping %s fd stage\n", states[state].name);
+			continue;
+		}
+
+		/*
+		 * Opening current TTYs require session to be already set up,
+		 * thus slave peers already handled now it's time for cttys,
+		 */
+		ret = open_fdinfos(me->pid.virt, &rsti(me)->tty_ctty, state);
+		if (ret)
+			break;
+	}
+
 	if (rsti(me)->fdt)
 		futex_inc_and_wake(&rsti(me)->fdt->fdt_lock);
 out:
diff --git a/include/rst_info.h b/include/rst_info.h
index f8d3ca8e0199..d850761498d6 100644
--- a/include/rst_info.h
+++ b/include/rst_info.h
@@ -30,6 +30,7 @@ struct rst_info {
 	struct list_head	fds;
 	struct list_head	eventpoll;
 	struct list_head	tty_slaves;
+	struct list_head	tty_ctty;
 
 	void			*premmapped_addr;
 	unsigned long		premmapped_len;
diff --git a/protobuf/tty.proto b/protobuf/tty.proto
index d4afe0642806..9da840c6e02b 100644
--- a/protobuf/tty.proto
+++ b/protobuf/tty.proto
@@ -29,6 +29,7 @@ enum TtyType {
 	PTY		= 1;
 	CONSOLE		= 2;
 	VT		= 3;
+	CTTY		= 4;
 }
 
 message tty_info_entry {
diff --git a/tty.c b/tty.c
index 8bed466b7ced..0bbd758f80e3 100644
--- a/tty.c
+++ b/tty.c
@@ -126,6 +126,7 @@ static LIST_HEAD(all_ttys);
 #define MAX_PTY_INDEX	1000
 #define CONSOLE_INDEX	1002
 #define VT_INDEX	1004
+#define CTTY_INDEX	1006
 #define INDEX_ERR	(MAX_TTYS + 1)
 
 static DECLARE_BITMAP(tty_bitmap, (MAX_TTYS << 1));
@@ -187,6 +188,14 @@ static struct tty_driver console_driver = {
 	.open			= open_simple_tty,
 };
 
+static struct tty_driver ctty_driver = {
+	.type			= TTY_TYPE__CTTY,
+	.subtype		= TTY_SUBTYPE_SLAVE,
+	.name			= "ctty",
+	.index			= CTTY_INDEX,
+	.open			= open_simple_tty,
+};
+
 static struct tty_driver vt_driver = {
 	.type			= TTY_TYPE__VT,
 	.name			= "vt",
@@ -231,6 +240,8 @@ struct tty_driver *get_tty_driver(int major, int minor)
 			return &ptm_driver;
 		else if (minor == 1)
 			return &console_driver;
+		else if (minor == 0)
+			return &ctty_driver;
 		break;
 	case TTY_MAJOR:
 		if (minor > MIN_NR_CONSOLES && minor < MAX_NR_CONSOLES)
@@ -626,6 +637,7 @@ static bool tty_is_master(struct tty_info *info)
 
 	switch (info->driver->type) {
 	case TTY_TYPE__CONSOLE:
+	case TTY_TYPE__CTTY:
 		return true;
 	case TTY_TYPE__VT:
 		if (!opts.shell_job)
@@ -972,15 +984,19 @@ static int tty_transport(FdinfoEntry *fe, struct file_desc *d)
 static void tty_collect_fd(struct file_desc *d, struct fdinfo_list_entry *fle,
 		struct rst_info *ri)
 {
+	struct tty_info *info = container_of(d, struct tty_info, d);
 	struct list_head *tgt;
 
 	/*
 	 * Unix98 pty slave peers requires the master peers being
-	 * opened before them
+	 * opened before them. In turn, current ttys should be opened
+	 * after the slave peers so session must alread exist.
 	 */
 
-	if (tty_is_master(container_of(d, struct tty_info, d)))
+	if (tty_is_master(info) && info->driver->type != TTY_TYPE__CTTY)
 		tgt = &ri->fds;
+	else if (info->driver->type == TTY_TYPE__CTTY)
+		tgt = &ri->tty_ctty;
 	else
 		tgt = &ri->tty_slaves;
 
@@ -1048,6 +1064,15 @@ static int tty_find_restoring_task(struct tty_info *info)
 		return 0;
 	}
 
+	/*
+	 * Current tty should be skipped here: the
+	 * underlied _real_ pty (or anything else
+	 * driver in future) should restore the
+	 * session.
+	 */
+	if (info->driver->type == TTY_TYPE__CTTY)
+		return 0;
+
 	if (info->tie->sid) {
 		if (!tty_is_master(info)) {
 			if (tty_has_active_pair(info))
@@ -1248,6 +1273,7 @@ static int collect_one_tty_info_entry(void *obj, ProtobufCMessage *msg)
 			return -1;
 		}
 		break;
+	case TTY_TYPE__CTTY:
 	case TTY_TYPE__CONSOLE:
 	case TTY_TYPE__VT:
 		if (info->tie->pty) {
@@ -1326,7 +1352,7 @@ static int collect_one_tty(void *obj, ProtobufCMessage *msg)
 	if (is_pty(info->driver) && info->tie->termios)
 		tty_test_and_set(info->tfe->tty_info_id, tty_active_pairs);
 
-	pr_info("Collected tty ID %#x\n", info->tfe->id);
+	pr_info("Collected tty ID %#x (%s)\n", info->tfe->id, info->driver->name);
 
 	list_add(&info->list, &all_ttys);
 	return file_desc_add(&info->d, info->tfe->id, &tty_desc_ops);
-- 
1.9.3



More information about the CRIU mailing list