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)
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:
......
......@@ -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;
......
......@@ -29,6 +29,7 @@ enum TtyType {
PTY = 1;
CONSOLE = 2;
VT = 3;
CTTY = 4;
}
message tty_info_entry {
......
......@@ -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);
......
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