[CRIU] Re: [PATCH 0/5] TTY c/r without controlling terminal

Cyrill Gorcunov gorcunov at openvz.org
Wed Sep 12 07:36:08 EDT 2012


On Wed, Sep 12, 2012 at 03:23:49PM +0400, Cyrill Gorcunov wrote:
> On Wed, Sep 12, 2012 at 03:21:15PM +0400, Pavel Emelyanov wrote:
> > 
> > OK, fix control ttys restore and I'll commit this.
> 
> Yeah, i'll post the final last patch in reply.

Andrew, could you please check if I'm not missed anything
in our file engine? Pavel, the post-open is not used simply
because we might receive-fd for controlling terminal if only
i've not missed anything.
-------------- next part --------------
>From 1ec3e4c7e1a3a0aeef2a117cca291b5bbfe92533 Mon Sep 17 00:00:00 2001
From: Cyrill Gorcunov <gorcunov at openvz.org>
Date: Tue, 11 Sep 2012 21:55:41 +0400
Subject: [PATCH] tty: Add restoration of controlling terminal v3

The idea behind is pretty simple -- once we find
that there is a controlling terminal present we
do call ioctl on appropriate /dev/pts/N.

This is done in a bit unusuall manner. When we
find that there is a controling terminal present
we do create an additional FdinfoEntry for it
with object id taken from existing master peer.

The file engine stack this new FdinfoEntry on
fd_info_head head list. Thus we will have at
least two entries on this list. One for real
Fdinfo associated with master peer and one for
our new generated Fdfinfo entry, it depends on
pid which one become a file master.

Finally when we obtain this new fdinfo (which
fd number is taken from service range) inside
our file engine -- we call the tty layer to
restore controlling terminal and then close
this service fd immediately.

v2:
 - restore control terminals via service fd,
   still need to speedup service fd retrieval.

v3:
 - use prepare_ctl_tty() helper to generate
   control terminal fdinfo entry

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 cr-restore.c      |    6 ++++
 files.c           |   39 ++++++++++++++++++++++++++++++
 include/crtools.h |    1 +
 include/files.h   |    1 +
 include/pstree.h  |    1 +
 include/tty.h     |    1 +
 tty.c             |   67 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 116 insertions(+), 0 deletions(-)

diff --git a/cr-restore.c b/cr-restore.c
index f0ad506..f6c99ad 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -134,6 +134,12 @@ static int prepare_shared(void)
 		ret = prepare_fd_pid(pi->pid.virt, pi->rst);
 		if (ret < 0)
 			break;
+
+		if (pi->ctl_tty_id) {
+			ret = prepare_ctl_tty(pi->pid.virt, pi->rst, pi->ctl_tty_id);
+			if (ret < 0)
+				break;
+		}
 	}
 
 	mark_pipe_master();
diff --git a/files.c b/files.c
index 8934d69..5e8cee9 100644
--- a/files.c
+++ b/files.c
@@ -196,6 +196,25 @@ static int collect_fd(int pid, FdinfoEntry *e, struct rst_info *rst_info)
 	return 0;
 }
 
+int prepare_ctl_tty(int pid, struct rst_info *rst_info, u32 ctl_tty_id)
+{
+	FdinfoEntry *e = xmalloc(sizeof(*e));
+	if (!e)
+		return -1;
+	fdinfo_entry__init(e);
+
+	e->id		= ctl_tty_id;
+	e->fd		= get_service_fd(CTL_TTY_OFF);
+	e->type		= FD_TYPES__TTY;
+
+	if (collect_fd(pid, e, rst_info)) {
+		xfree(e);
+		return -1;
+	}
+
+	return 0;
+}
+
 int prepare_fd_pid(int pid, struct rst_info *rst_info)
 {
 	int fdinfo_fd, ret = 0;
@@ -386,6 +405,13 @@ static int open_fd(int pid, FdinfoEntry *fe, struct file_desc *d)
 				return -1;
 			}
 
+			if (fle->fe->fd == get_service_fd(CTL_TTY_OFF)) {
+				tty_restore_ctl_terminal(d);
+				close(fle->fe->fd);
+				pr_err("Close CTL_TTY_OFF %d\n", fle->fe->fd);
+				continue;
+			}
+
 			fcntl(fle->fe->fd, F_SETFD, fle->fe->flags);
 
 			continue;
@@ -397,6 +423,12 @@ static int open_fd(int pid, FdinfoEntry *fe, struct file_desc *d)
 		}
 	}
 
+	if (fe->fd == get_service_fd(CTL_TTY_OFF)) {
+		tty_restore_ctl_terminal(d);
+		close(fe->fd);
+		pr_err("Close CTL_TTY_OFF %d\n", fe->fd);
+	}
+
 	close(sock);
 	return 0;
 }
@@ -423,6 +455,13 @@ static int receive_fd(int pid, FdinfoEntry *fe, struct file_desc *d)
 	if (reopen_fd_as(fe->fd, tmp) < 0)
 		return -1;
 
+	if (fe->fd == get_service_fd(CTL_TTY_OFF)) {
+		tty_restore_ctl_terminal(d);
+		close(fe->fd);
+		pr_err("Close CTL_TTY_OFF %d\n", fe->fd);
+		return 0;
+	}
+
 	fcntl(tmp, F_SETFD, fe->flags);
 	return 0;
 }
diff --git a/include/crtools.h b/include/crtools.h
index 459b64f..ad36c8c 100644
--- a/include/crtools.h
+++ b/include/crtools.h
@@ -106,6 +106,7 @@ enum {
 	IMG_FD_OFF,
 	SELF_EXE_FD_OFF,
 	PROC_FD_OFF,
+	CTL_TTY_OFF,
 };
 
 int get_service_fd(int type);
diff --git a/include/files.h b/include/files.h
index 2a30846..4791377 100644
--- a/include/files.h
+++ b/include/files.h
@@ -87,6 +87,7 @@ extern void show_saved_files(void);
 
 extern int prepare_fds(struct pstree_item *me);
 extern int prepare_fd_pid(int pid, struct rst_info *rst_info);
+extern int prepare_ctl_tty(int pid, struct rst_info *rst_info, u32 ctl_tty_id);
 extern int prepare_shared_fdinfo(void);
 extern int get_filemap_fd(int pid, VmaEntry *vma_entry);
 extern int prepare_fs(int pid);
diff --git a/include/pstree.h b/include/pstree.h
index dc7f232..e78326e 100644
--- a/include/pstree.h
+++ b/include/pstree.h
@@ -11,6 +11,7 @@ struct pstree_item {
 	pid_t			pgid;
 	pid_t			sid;
 	pid_t			born_sid;
+	u32			ctl_tty_id;
 	int			state;		/* TASK_XXX constants */
 	int			nr_threads;	/* number of threads */
 	struct pid		*threads;	/* array of threads */
diff --git a/include/tty.h b/include/tty.h
index 66d4cdf..144b94b 100644
--- a/include/tty.h
+++ b/include/tty.h
@@ -20,5 +20,6 @@ extern int dump_tty(struct fd_parms *p, int lfd, const struct cr_fdset *set);
 extern int collect_tty(void);
 extern int tty_is_master(struct fdinfo_list_entry *le);
 extern int tty_prepare_shared(void);
+extern int tty_restore_ctl_terminal(struct file_desc *d);
 
 #endif /* CR_TTY_H__ */
diff --git a/tty.c b/tty.c
index eb09202..58ad7cc 100644
--- a/tty.c
+++ b/tty.c
@@ -320,6 +320,50 @@ static int tty_get_pgrp(int fd)
 	return prgp;
 }
 
+static int tty_set_sid(int fd)
+{
+	if (ioctl(fd, TIOCSCTTY, 1)) {
+		pr_perror("Can't set sid on terminal fd %d\n", fd);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int tty_set_prgp(int fd, int group)
+{
+	if (ioctl(fd, TIOCSPGRP, &group)) {
+		pr_perror("Failed to set group %d on %d\n", group, fd);
+		return -1;
+	}
+	return 0;
+}
+
+int tty_restore_ctl_terminal(struct file_desc *d)
+{
+	struct tty_info *info = container_of(d, struct tty_info, d);
+	int fd, ret = -1;
+	char pts_name[64];
+
+	snprintf(pts_name, sizeof(pts_name), PTS_FMT, info->tie->pty->index);
+	fd = open(pts_name, O_RDONLY);
+	if (fd < 0) {
+		pr_perror("Can't open %s", pts_name);
+		return -1;
+	}
+
+	pr_info("Restore session %d by %d tty (index %d)\n",
+		 info->tie->sid, (int)getpid(),
+		 info->tie->pty->index);
+
+	ret = tty_set_sid(fd);
+	if (!ret)
+		ret = tty_set_prgp(fd, info->tie->pgrp);
+
+	close(fd);
+	return ret;
+}
+
 static char *tty_type(struct tty_info *info)
 {
 	static char *tty_types[] = {
@@ -529,17 +573,40 @@ static struct file_desc_ops tty_desc_ops = {
 	.want_transport = tty_transport,
 };
 
+static int tty_find_restoring_task(struct tty_info *info)
+{
+	struct pstree_item *item;
+
+	if (info->tie->sid == 0)
+		return 0;
+
+	pr_info("Set a control terminal to %d\n", info->tie->sid);
+
+	for_each_pstree_item(item) {
+		if (item->sid == info->tie->sid) {
+			item->ctl_tty_id = info->tfe->id;
+			return 0;
+		}
+	}
+
+	pr_err("No task found with sid %d\n", info->tie->sid);
+	return -1;
+}
+
 static int tty_setup_slavery(void)
 {
 	struct tty_info *info, *peer, *m;
 
 	list_for_each_entry(info, &all_ttys, list) {
+		tty_find_restoring_task(info);
 
 		peer = info;
 		list_for_each_entry_safe_continue(peer, m, &all_ttys, list) {
 			if (peer->tie->pty->index != info->tie->pty->index)
 				continue;
 
+			tty_find_restoring_task(peer);
+
 			list_add(&peer->sibling, &info->sibling);
 			list_del(&peer->list);
 		}
-- 
1.7.7.6



More information about the CRIU mailing list