[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