Commit 243e58f0 authored by Cyrill Gorcunov's avatar Cyrill Gorcunov Committed by Pavel Emelyanov

tty: Implement support of current tty

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: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 80a134a4
...@@ -607,6 +607,7 @@ int prepare_fd_pid(struct pstree_item *item) ...@@ -607,6 +607,7 @@ int prepare_fd_pid(struct pstree_item *item)
INIT_LIST_HEAD(&rst_info->fds); INIT_LIST_HEAD(&rst_info->fds);
INIT_LIST_HEAD(&rst_info->eventpoll); INIT_LIST_HEAD(&rst_info->eventpoll);
INIT_LIST_HEAD(&rst_info->tty_slaves); INIT_LIST_HEAD(&rst_info->tty_slaves);
INIT_LIST_HEAD(&rst_info->tty_ctty);
if (!fdinfo_per_id) { if (!fdinfo_per_id) {
img = open_image(CR_FD_FDINFO, O_RSTR, pid); img = open_image(CR_FD_FDINFO, O_RSTR, pid);
...@@ -1022,6 +1023,21 @@ int prepare_fds(struct pstree_item *me) ...@@ -1022,6 +1023,21 @@ int prepare_fds(struct pstree_item *me)
break; 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) if (rsti(me)->fdt)
futex_inc_and_wake(&rsti(me)->fdt->fdt_lock); futex_inc_and_wake(&rsti(me)->fdt->fdt_lock);
out: out:
......
...@@ -30,6 +30,7 @@ struct rst_info { ...@@ -30,6 +30,7 @@ struct rst_info {
struct list_head fds; struct list_head fds;
struct list_head eventpoll; struct list_head eventpoll;
struct list_head tty_slaves; struct list_head tty_slaves;
struct list_head tty_ctty;
void *premmapped_addr; void *premmapped_addr;
unsigned long premmapped_len; unsigned long premmapped_len;
......
...@@ -29,6 +29,7 @@ enum TtyType { ...@@ -29,6 +29,7 @@ enum TtyType {
PTY = 1; PTY = 1;
CONSOLE = 2; CONSOLE = 2;
VT = 3; VT = 3;
CTTY = 4;
} }
message tty_info_entry { message tty_info_entry {
......
...@@ -126,6 +126,7 @@ static LIST_HEAD(all_ttys); ...@@ -126,6 +126,7 @@ static LIST_HEAD(all_ttys);
#define MAX_PTY_INDEX 1000 #define MAX_PTY_INDEX 1000
#define CONSOLE_INDEX 1002 #define CONSOLE_INDEX 1002
#define VT_INDEX 1004 #define VT_INDEX 1004
#define CTTY_INDEX 1006
#define INDEX_ERR (MAX_TTYS + 1) #define INDEX_ERR (MAX_TTYS + 1)
static DECLARE_BITMAP(tty_bitmap, (MAX_TTYS << 1)); static DECLARE_BITMAP(tty_bitmap, (MAX_TTYS << 1));
...@@ -187,6 +188,14 @@ static struct tty_driver console_driver = { ...@@ -187,6 +188,14 @@ static struct tty_driver console_driver = {
.open = open_simple_tty, .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 = { static struct tty_driver vt_driver = {
.type = TTY_TYPE__VT, .type = TTY_TYPE__VT,
.name = "vt", .name = "vt",
...@@ -231,6 +240,8 @@ struct tty_driver *get_tty_driver(int major, int minor) ...@@ -231,6 +240,8 @@ struct tty_driver *get_tty_driver(int major, int minor)
return &ptm_driver; return &ptm_driver;
else if (minor == 1) else if (minor == 1)
return &console_driver; return &console_driver;
else if (minor == 0)
return &ctty_driver;
break; break;
case TTY_MAJOR: case TTY_MAJOR:
if (minor > MIN_NR_CONSOLES && minor < MAX_NR_CONSOLES) if (minor > MIN_NR_CONSOLES && minor < MAX_NR_CONSOLES)
...@@ -626,6 +637,7 @@ static bool tty_is_master(struct tty_info *info) ...@@ -626,6 +637,7 @@ static bool tty_is_master(struct tty_info *info)
switch (info->driver->type) { switch (info->driver->type) {
case TTY_TYPE__CONSOLE: case TTY_TYPE__CONSOLE:
case TTY_TYPE__CTTY:
return true; return true;
case TTY_TYPE__VT: case TTY_TYPE__VT:
if (!opts.shell_job) if (!opts.shell_job)
...@@ -972,15 +984,19 @@ static int tty_transport(FdinfoEntry *fe, struct file_desc *d) ...@@ -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, static void tty_collect_fd(struct file_desc *d, struct fdinfo_list_entry *fle,
struct rst_info *ri) struct rst_info *ri)
{ {
struct tty_info *info = container_of(d, struct tty_info, d);
struct list_head *tgt; struct list_head *tgt;
/* /*
* Unix98 pty slave peers requires the master peers being * 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; tgt = &ri->fds;
else if (info->driver->type == TTY_TYPE__CTTY)
tgt = &ri->tty_ctty;
else else
tgt = &ri->tty_slaves; tgt = &ri->tty_slaves;
...@@ -1048,6 +1064,15 @@ static int tty_find_restoring_task(struct tty_info *info) ...@@ -1048,6 +1064,15 @@ static int tty_find_restoring_task(struct tty_info *info)
return 0; 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 (info->tie->sid) {
if (!tty_is_master(info)) { if (!tty_is_master(info)) {
if (tty_has_active_pair(info)) if (tty_has_active_pair(info))
...@@ -1248,6 +1273,7 @@ static int collect_one_tty_info_entry(void *obj, ProtobufCMessage *msg) ...@@ -1248,6 +1273,7 @@ static int collect_one_tty_info_entry(void *obj, ProtobufCMessage *msg)
return -1; return -1;
} }
break; break;
case TTY_TYPE__CTTY:
case TTY_TYPE__CONSOLE: case TTY_TYPE__CONSOLE:
case TTY_TYPE__VT: case TTY_TYPE__VT:
if (info->tie->pty) { if (info->tie->pty) {
...@@ -1326,7 +1352,7 @@ static int collect_one_tty(void *obj, ProtobufCMessage *msg) ...@@ -1326,7 +1352,7 @@ static int collect_one_tty(void *obj, ProtobufCMessage *msg)
if (is_pty(info->driver) && info->tie->termios) if (is_pty(info->driver) && info->tie->termios)
tty_test_and_set(info->tfe->tty_info_id, tty_active_pairs); 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); list_add(&info->list, &all_ttys);
return file_desc_add(&info->d, info->tfe->id, &tty_desc_ops); return file_desc_add(&info->d, info->tfe->id, &tty_desc_ops);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment