[CRIU] [PATCH 11/11] tty: Add dump and restore of /dev/console opened
Cyrill Gorcunov
gorcunov at openvz.org
Mon Sep 29 09:25:37 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.
The underlied driver may have own .ioctls which we
don't account for a while but stick with simple
solution first to see how it goes:
- simply fetch general tty parameters such as termios
and winsize and save them in image
- the image entry will have own tty type TTY_TYPE__CONSOLE
- on restore simply open the console by predefinde path
as /dev/console and restore the parameters
- because tty_info::tie::pty = NULL for consoles put
BUG_ON where appropriate
Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
tty.c | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 161 insertions(+), 12 deletions(-)
diff --git a/tty.c b/tty.c
index 07889a6ec605..12a3ef086194 100644
--- a/tty.c
+++ b/tty.c
@@ -362,6 +362,8 @@ static int tty_restore_ctl_terminal(struct file_desc *d, int fd)
if (!is_service_fd(fd, CTL_TTY_OFF))
return 0;
+ BUG_ON(!info->tie->pty);
+
snprintf(pts_name, sizeof(pts_name), PTS_FMT, info->tie->pty->index);
slave = open(pts_name, O_RDONLY);
if (slave < 0) {
@@ -420,7 +422,8 @@ static bool tty_has_active_pair(struct tty_info *info)
static void tty_show_pty_info(char *prefix, struct tty_info *info)
{
pr_info("%s type %s id %#x index %d (master %d sid %d pgrp %d inherit %d)\n",
- prefix, tty_type(info->major, info->minor), info->tfe->id, info->tie->pty->index,
+ prefix, tty_type(info->major, info->minor), info->tfe->id,
+ info->tie->pty ? info->tie->pty->index : -1,
tty_is_master(info), info->tie->sid, info->tie->pgrp, info->inherit);
}
@@ -472,6 +475,7 @@ static int pty_open_slaves(struct tty_info *info)
struct tty_info *slave;
char pts_name[64];
+ BUG_ON(!info->tie->pty);
snprintf(pts_name, sizeof(pts_name), PTS_FMT, info->tie->pty->index);
sock = socket(PF_UNIX, SOCK_DGRAM, 0);
@@ -554,6 +558,7 @@ static int pty_open_unpaired_slave(struct file_desc *d, struct tty_info *slave)
} else {
char pts_name[64];
+ BUG_ON(!slave->tie->pty);
snprintf(pts_name, sizeof(pts_name), PTS_FMT, slave->tie->pty->index);
master = pty_open_ptmx_index(O_RDONLY, slave->tie->pty->index);
@@ -616,6 +621,7 @@ static int pty_open_ptmx(struct tty_info *info)
{
int master = -1;
+ BUG_ON(!info->tie->pty);
master = pty_open_ptmx_index(info->tfe->flags, info->tie->pty->index);
if (master < 0) {
pr_perror("Can't open %x (index %d)",
@@ -653,6 +659,30 @@ err:
return -1;
}
+static int console_open(struct tty_info *info)
+{
+ const char console_path[] = "/dev/console";
+ int console = -1;
+
+ console = open(console_path, info->tfe->flags);
+ if (console < 0) {
+ pr_perror("Can't open %s %x",
+ console_path, info->tfe->id);
+ return -1;
+ }
+
+ if (rst_file_params(console, info->tfe->fown, info->tfe->flags))
+ goto err;
+
+ if (restore_tty_params(console, info))
+ goto err;
+
+ return console;
+err:
+ close_safe(&console);
+ return -1;
+}
+
static int tty_open(struct file_desc *d)
{
struct tty_info *info = container_of(d, struct tty_info, d);
@@ -662,11 +692,15 @@ static int tty_open(struct file_desc *d)
if (!info->create)
return receive_tty(info);
- if (!tty_is_master(info))
- return pty_open_unpaired_slave(d, info);
-
- return pty_open_ptmx(info);
+ if (info->tie->type == TTY_TYPE__PTY) {
+ if (!tty_is_master(info))
+ return pty_open_unpaired_slave(d, info);
+ return pty_open_ptmx(info);
+ } else if (info->tie->type == TTY_TYPE__CONSOLE)
+ return console_open(info);
+ pr_err("Unexpected type of TTY %d\n", info->tie->type);
+ return -1;
}
static int tty_transport(FdinfoEntry *fe, struct file_desc *d)
@@ -843,11 +877,16 @@ int tty_setup_slavery(void)
struct tty_info *info, *peer, *m;
list_for_each_entry(info, &all_ttys, list) {
+ if (info->tie->type != TTY_TYPE__PTY)
+ continue;
if (tty_find_restoring_task(info))
return -1;
peer = info;
list_for_each_entry_safe_continue(peer, m, &all_ttys, list) {
+ if (peer->tie->type != TTY_TYPE__PTY)
+ continue;
+
if (peer->tie->pty->index != info->tie->pty->index)
continue;
@@ -937,18 +976,21 @@ static int collect_one_tty_info_entry(void *obj, ProtobufCMessage *msg)
info->tie = pb_msg(msg, TtyInfoEntry);
- if (info->tie->type != TTY_TYPE__PTY) {
+ if (info->tie->type == TTY_TYPE__PTY) {
+ if (!info->tie->pty) {
+ pr_err("No PTY data found (id %x), corrupted image?\n",
+ info->tie->id);
+ return -1;
+ }
+ } else if (info->tie->type == TTY_TYPE__CONSOLE) {
+ /* Nothing */;
+ } else {
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;
- }
-
+ pr_info("Collected tty-info ID %#x\n", info->tie->id);
INIT_LIST_HEAD(&info->list);
list_add(&info->list, &all_tty_info_entries);
@@ -1214,6 +1256,111 @@ static int dump_one_pty(int lfd, u32 id, const struct fd_parms *p, int major, in
return ret;
}
+static int dump_console_info(int lfd, u32 id, const struct fd_parms *p, int major, int minor, int index)
+{
+ TtyInfoEntry info = TTY_INFO_ENTRY__INIT;
+ TermiosEntry termios = TERMIOS_ENTRY__INIT;
+ TermiosEntry termios_locked = TERMIOS_ENTRY__INIT;
+ WinsizeEntry winsize = WINSIZE_ENTRY__INIT;
+ struct tty_dump_info *dinfo;
+
+ struct termios t;
+ struct winsize w;
+
+ int ret = -1;
+
+ /*
+ * Make sure the structures the system provides us
+ * correlates well with protobuf templates.
+ */
+ BUILD_BUG_ON(ARRAY_SIZE(t.c_cc) < TERMIOS_NCC);
+ BUILD_BUG_ON(sizeof(termios.c_cc) != sizeof(void *));
+ BUILD_BUG_ON((sizeof(termios.c_cc) * TERMIOS_NCC) < sizeof(t.c_cc));
+
+ dinfo = xmalloc(sizeof(*dinfo));
+ if (!dinfo)
+ return -1;
+
+ /*
+ * Make sure no @sid and @pgrp here since
+ * that's how we check if we need to validate
+ * this particular peer as a contol terminal
+ * (which system console can't be).
+ */
+ dinfo->id = id;
+ dinfo->sid = 0;
+ dinfo->pgrp = 0;
+ dinfo->fd = p->fd;
+ dinfo->major = major;
+ dinfo->minor = minor;
+
+ list_add_tail(&dinfo->list, &all_ttys);
+
+ info.id = id;
+ info.type = TTY_TYPE__CONSOLE;
+ info.sid = 0;
+ info.pgrp = 0;
+ info.rdev = p->stat.st_rdev;
+
+ info.termios = &termios;
+ info.termios_locked = &termios_locked;
+ info.winsize = &winsize;
+
+ termios.n_c_cc = TERMIOS_NCC;
+ termios.c_cc = xmalloc(pb_repeated_size(&termios, c_cc));
+
+ termios_locked.n_c_cc = TERMIOS_NCC;
+ termios_locked.c_cc = xmalloc(pb_repeated_size(&termios_locked, c_cc));
+
+ if (!termios.c_cc || !termios_locked.c_cc)
+ goto out;
+
+ memzero(&t, sizeof(t));
+ if (ioctl(lfd, TCGETS, &t) < 0) {
+ pr_perror("Can't get tty params on %x", id);
+ goto out;
+ }
+ termios_copy(&termios, &t);
+
+ memzero(&t, sizeof(t));
+ if (ioctl(lfd, TIOCGLCKTRMIOS, &t) < 0) {
+ pr_perror("Can't get tty locked params on %x", id);
+ goto out;
+ }
+ termios_copy(&termios_locked, &t);
+
+ memzero(&w, sizeof(w));
+ if (ioctl(lfd, TIOCGWINSZ, &w) < 0) {
+ pr_perror("Can't get tty window params on %x", id);
+ goto out;
+ }
+ winsize_copy(&winsize, &w);
+
+ ret = pb_write_one(fdset_fd(glob_fdset, CR_FD_TTY_INFO), &info, PB_TTY_INFO);
+out:
+ xfree(termios.c_cc);
+ xfree(termios_locked.c_cc);
+ return ret;
+}
+
+static int dump_one_console(int lfd, u32 id, const struct fd_parms *p, int major, int minor)
+{
+ TtyFileEntry e = TTY_FILE_ENTRY__INIT;
+ int ret = 0;
+
+ e.id = id;
+ e.tty_info_id = tty_gen_id(major, CONSOLE_START);
+ e.flags = p->flags;
+ e.fown = (FownEntry *)&p->fown;
+
+ if (!tty_test_and_set(e.tty_info_id, tty_bitmap))
+ ret = dump_console_info(lfd, e.tty_info_id, p, major, minor, CONSOLE_START);
+
+ if (!ret)
+ ret = pb_write_one(fdset_fd(glob_fdset, CR_FD_TTY_FILES), &e, PB_TTY_FILE);
+ return ret;
+}
+
static int dump_one_tty(int lfd, u32 id, const struct fd_parms *p)
{
int major = major(p->stat.st_rdev);
@@ -1226,6 +1373,8 @@ static int dump_one_tty(int lfd, u32 id, const struct fd_parms *p)
case TTYAUX_MAJOR:
if (minor == 0 || minor == 2)
return dump_one_pty(lfd, id, p, major, minor);
+ else if (minor == 1)
+ return dump_one_console(lfd, id, p, major, minor);
break;
case UNIX98_PTY_MASTER_MAJOR ... (UNIX98_PTY_MASTER_MAJOR + UNIX98_PTY_MAJOR_COUNT - 1):
case UNIX98_PTY_SLAVE_MAJOR:
--
1.9.3
More information about the CRIU
mailing list