[CRIU] [RFC] tty: Add support of system console (/dev/console)
Cyrill Gorcunov
gorcunov at openvz.org
Wed Oct 15 02:27:49 PDT 2014
/dev/console is a system console which provided
by the system with major 5 and minor 1. It's usually
configured on system startup with console= option
and underlied driver is resposible to deliver messages
to the console user.
Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
This patch is on top of previous
[PATCH 0/5] tty: Use reg-files engine to save paths to tty peers
please take a look.
include/tty.h | 1 +
protobuf/tty.proto | 1 +
tty.c | 165 +++++++++++++++++++++++++++++++++++++++--------------
3 files changed, 124 insertions(+), 43 deletions(-)
diff --git a/include/tty.h b/include/tty.h
index 7181cdd00e6c..658981304466 100644
--- a/include/tty.h
+++ b/include/tty.h
@@ -10,6 +10,7 @@ enum {
TTY_TYPE_UNKNOWN = 0,
TTY_TYPE_PTM = 1,
TTY_TYPE_PTS = 2,
+ TTY_TYPE_CONSOLE = 3,
TTY_TYPE_MAX
};
diff --git a/protobuf/tty.proto b/protobuf/tty.proto
index 8942965c580b..18470a9af0b7 100644
--- a/protobuf/tty.proto
+++ b/protobuf/tty.proto
@@ -26,6 +26,7 @@ message tty_pty_entry {
enum TtyType {
UNKNOWN = 0;
PTY = 1;
+ CONSOLE = 2;
}
message tty_info_entry {
diff --git a/tty.c b/tty.c
index e5e64878a736..63b3b810bcfe 100644
--- a/tty.c
+++ b/tty.c
@@ -114,7 +114,10 @@ static LIST_HEAD(all_ttys);
* This particular bitmap requires 256 bytes of memory.
* Pretty acceptable trade off in a sake of simplicity.
*/
-#define MAX_TTYS 1024
+#define MAX_TTYS 1024
+#define MAX_PTY_INDEX 1000
+#define CONSOLE_INDEX 1002
+
static DECLARE_BITMAP(tty_bitmap, (MAX_TTYS << 1));
static DECLARE_BITMAP(tty_active_pairs, (MAX_TTYS << 1));
@@ -229,7 +232,7 @@ static int parse_pty_index(u32 id, int lfd, const struct fd_parms *p, int type)
}
}
- if (index > MAX_TTYS) {
+ if (index > MAX_PTY_INDEX) {
pr_err("Index %d on tty %x is too big\n", index, id);
return -1;
}
@@ -296,6 +299,7 @@ static struct tty_info *pty_alloc_fake(struct tty_info *info, int type)
info->tfe->id, info->reg_d);
BUG_ON(!info->reg_d);
+ BUG_ON((type != TTY_TYPE_PTM) && (type != TTY_TYPE_PTS));
orig = container_of(info->reg_d, struct reg_file_info, d);
p = xzalloc(sizeof(*p) +
@@ -512,20 +516,29 @@ static int tty_set_prgp(int fd, int group)
static int tty_restore_ctl_terminal(struct file_desc *d, int fd)
{
struct tty_info *info = container_of(d, struct tty_info, d);
- struct tty_info *fake;
- int slave, ret = -1;
+ struct tty_info *fake = NULL;
+ int slave = -1, ret = -1;
if (!is_service_fd(fd, CTL_TTY_OFF))
return 0;
- fake = pty_alloc_fake_slave(info);
- if (!fake)
- goto err;
- slave = open_pty_reg(fake, O_RDONLY);
- if (slave < 0) {
- pr_perror("Can't open %s", path_from_reg(fake->reg_d));
- goto err;
- }
+ if (info->type == TTY_TYPE_PTM || info->type == TTY_TYPE_PTS) {
+ fake = pty_alloc_fake_slave(info);
+ if (!fake)
+ goto err;
+ slave = open_pty_reg(fake, O_RDONLY);
+ if (slave < 0) {
+ pr_perror("Can't open %s", path_from_reg(fake->reg_d));
+ goto err;
+ }
+ } else if (info->type == TTY_TYPE_CONSOLE) {
+ slave = open_pty_reg(info, O_RDONLY);
+ if (slave < 0) {
+ pr_perror("Can't open %s", path_from_reg(info->reg_d));
+ goto err;
+ }
+ } else
+ BUG();
pr_info("Restore session %d by %d tty (index %d)\n",
info->tie->sid, (int)getpid(),
@@ -548,6 +561,8 @@ int tty_type(int major, int minor)
case TTYAUX_MAJOR:
if (minor == 0 || minor == 2)
return TTY_TYPE_PTM;
+ else if (minor == 1)
+ return TTY_TYPE_CONSOLE;
break;
case UNIX98_PTY_MASTER_MAJOR ... (UNIX98_PTY_MASTER_MAJOR + UNIX98_PTY_MAJOR_COUNT - 1):
return TTY_TYPE_PTM;
@@ -564,13 +579,16 @@ static char *tty_name(int type)
return "ptmx";
case TTY_TYPE_PTS:
return "pts";
+ case TTY_TYPE_CONSOLE:
+ return "console";
}
return "unknown";
}
static bool tty_is_master(struct tty_info *info)
{
- return info->type == TTY_TYPE_PTM;
+ return info->type == TTY_TYPE_PTM ||
+ info->type == TTY_TYPE_CONSOLE;
}
static bool tty_is_hung(struct tty_info *info)
@@ -816,6 +834,26 @@ err:
return -1;
}
+static int open_console(struct tty_info *info)
+{
+ int fd = -1;
+
+ fd = open_pty_reg(info, info->tfe->flags);
+ if (fd < 0) {
+ pr_perror("Can't open console %x",
+ info->tfe->id);
+ return -1;
+ }
+
+ if (restore_tty_params(fd, info))
+ goto err;
+
+ return fd;
+err:
+ close_safe(&fd);
+ return -1;
+}
+
static int tty_open(struct file_desc *d)
{
struct tty_info *info = container_of(d, struct tty_info, d);
@@ -828,8 +866,10 @@ static int tty_open(struct file_desc *d)
if (!tty_is_master(info))
return pty_open_unpaired_slave(d, info);
- return pty_open_ptmx(info);
-
+ if (info->type == TTY_TYPE_CONSOLE)
+ return open_console(info);
+ else
+ return pty_open_ptmx(info);
}
static int tty_transport(FdinfoEntry *fe, struct file_desc *d)
@@ -1058,8 +1098,9 @@ static int verify_termios(u32 id, TermiosEntry *e)
static int verify_info(struct tty_info *info)
{
if (info->type != TTY_TYPE_PTM &&
- info->type != TTY_TYPE_PTS) {
- pr_err("Unknown type %d master peer %x\n",
+ info->type != TTY_TYPE_PTS &&
+ info->type != TTY_TYPE_CONSOLE) {
+ pr_err("Unknown type %d peer %x\n",
info->type, info->tfe->id);
return -1;
}
@@ -1107,18 +1148,27 @@ static int collect_one_tty_info_entry(void *obj, ProtobufCMessage *msg)
info->tie = pb_msg(msg, TtyInfoEntry);
- if (info->tie->type != TTY_TYPE__PTY) {
+ switch (info->tie->type) {
+ case TTY_TYPE__PTY:
+ if (!info->tie->pty) {
+ pr_err("No PTY data found (id %x), corrupted image?\n",
+ info->tie->id);
+ return -1;
+ }
+ break;
+ case TTY_TYPE__CONSOLE:
+ if (info->tie->pty) {
+ pr_err("PTY data found (id %x), corrupted image?\n",
+ info->tie->id);
+ return -1;
+ }
+ break;
+ default:
pr_err("Unexpected TTY type %d (id %x)\n",
info->tie->type, info->tie->id);
return -1;
}
- if (!info->tie->pty) {
- pr_err("No PTY data found (id %x), corrupted image?\n",
- info->tie->id);
- return -1;
- }
-
INIT_LIST_HEAD(&info->list);
list_add(&info->list, &all_tty_info_entries);
@@ -1171,10 +1221,16 @@ static int collect_one_tty(void *obj, ProtobufCMessage *msg)
info->reg_d = find_file_desc_raw(FD_TYPES__REG, info->tfe->id);
if (!info->reg_d) {
- info->reg_d = pty_alloc_fake_reg_d(info, true);
- if (!info->reg_d) {
- pr_err("Can't generate new reg_d descriptor for id %#x\n",
- info->tfe->id);
+ if (info->type == TTY_TYPE_PTM ||
+ info->type == TTY_TYPE_PTS) {
+ info->reg_d = pty_alloc_fake_reg_d(info, true);
+ if (!info->reg_d) {
+ pr_err("Can't generate new reg_d descriptor for id %#x\n",
+ info->tfe->id);
+ return -1;
+ }
+ } else {
+ pr_err("No reg_d descriptor for id %#x\n", info->tfe->id);
return -1;
}
}
@@ -1195,8 +1251,10 @@ static int collect_one_tty(void *obj, ProtobufCMessage *msg)
* can't be used. Most likely they appear if a user has
* dumped program when it was closing a peer.
*/
- if (info->tie->termios)
- tty_test_and_set(info->tfe->tty_info_id, tty_active_pairs);
+ if (info->type == TTY_TYPE_PTM || info->type == TTY_TYPE_PTS) {
+ if (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);
@@ -1264,7 +1322,7 @@ int dump_verify_tty_sids(void)
return ret;
}
-static int dump_pty_info(int lfd, u32 id, const struct fd_parms *p, int type, int index)
+static int dump_tty_info(int lfd, u32 id, const struct fd_parms *p, int type, int index)
{
TtyInfoEntry info = TTY_INFO_ENTRY__INIT;
TermiosEntry termios = TERMIOS_ENTRY__INIT;
@@ -1304,18 +1362,28 @@ static int dump_pty_info(int lfd, u32 id, const struct fd_parms *p, int type, in
list_add_tail(&dinfo->list, &all_ttys);
info.id = id;
- info.type = TTY_TYPE__PTY;
info.sid = pti->sid;
info.pgrp = pti->pgrp;
info.rdev = p->stat.st_rdev;
- info.pty = &pty;
+
+ switch (type) {
+ case TTY_TYPE_PTM:
+ case TTY_TYPE_PTS:
+ info.type = TTY_TYPE__PTY;
+ info.pty = &pty;
+ pty.index = index;
+ break;
+ case TTY_TYPE_CONSOLE:
+ info.type = TTY_TYPE__CONSOLE;
+ break;
+ default:
+ BUG();
+ }
info.locked = pti->st_lock;
info.exclusive = pti->st_excl;
info.packet_mode = pti->st_pckt;
- pty.index = index;
-
/*
* Nothing we can do on hanging up terminal,
* just write out minimum information we can
@@ -1331,7 +1399,8 @@ static int dump_pty_info(int lfd, u32 id, const struct fd_parms *p, int type, in
* not yet supported by our tool and better to
* inform a user about such situation.
*/
- tty_test_and_set(id, tty_active_pairs);
+ if (type == TTY_TYPE_PTM || type == TTY_TYPE_PTS)
+ tty_test_and_set(id, tty_active_pairs);
info.termios = &termios;
info.termios_locked = &termios_locked;
@@ -1374,10 +1443,10 @@ out:
return ret;
}
-static int dump_one_pty(int lfd, u32 id, const struct fd_parms *p)
+static int dump_one_tty(int lfd, u32 id, const struct fd_parms *p)
{
TtyFileEntry e = TTY_FILE_ENTRY__INIT;
- int ret = 0, type, index;
+ int ret = 0, type, index = -1;
pr_info("Dumping tty %d with id %#x\n", lfd, id);
@@ -1385,9 +1454,19 @@ static int dump_one_pty(int lfd, u32 id, const struct fd_parms *p)
return -1;
type = tty_type(major(p->stat.st_rdev), minor(p->stat.st_rdev));
- index = parse_pty_index(id, lfd, p, type);
- if (index < 0)
- return -1;
+ switch (type) {
+ case TTY_TYPE_PTM:
+ case TTY_TYPE_PTS:
+ index = parse_pty_index(id, lfd, p, type);
+ if (index < 0)
+ return -1;
+ break;
+ case TTY_TYPE_CONSOLE:
+ index = CONSOLE_INDEX;
+ break;
+ default:
+ BUG();
+ }
e.id = id;
e.tty_info_id = tty_gen_id(type, index);
@@ -1415,7 +1494,7 @@ static int dump_one_pty(int lfd, u32 id, const struct fd_parms *p)
*/
if (!tty_test_and_set(e.tty_info_id, tty_bitmap))
- ret = dump_pty_info(lfd, e.tty_info_id, p, type, index);
+ ret = dump_tty_info(lfd, e.tty_info_id, p, type, index);
if (!ret)
ret = pb_write_one(img_from_set(glob_imgset, CR_FD_TTY_FILES), &e, PB_TTY_FILE);
@@ -1424,7 +1503,7 @@ static int dump_one_pty(int lfd, u32 id, const struct fd_parms *p)
const struct fdtype_ops tty_dump_ops = {
.type = FD_TYPES__TTY,
- .dump = dump_one_pty,
+ .dump = dump_one_tty,
};
int tty_prep_fds(void)
--
1.9.3
More information about the CRIU
mailing list