[CRIU] Re: [PATCH 5/6] tty: Restore orphan slavery peers

Cyrill Gorcunov gorcunov at openvz.org
Fri Sep 14 08:45:48 EDT 2012


On Fri, Sep 14, 2012 at 04:37:10PM +0400, Cyrill Gorcunov wrote:
> 
> We've two stages -- 1st when we don't have fdinfo assigned (early stage)
> at this time we bind master/slave peers and figure out control terminal.
> 
> The second stage is when all fds are assigned and we figures out which
> fake master we might need.

Here is an update.
-------------- next part --------------
>From 45a7accb0387b0ae48a9c0f41a313f17c699d995 Mon Sep 17 00:00:00 2001
From: Cyrill Gorcunov <gorcunov at openvz.org>
Date: Thu, 13 Sep 2012 21:07:57 +0400
Subject: [PATCH] tty: Restore orphan slavery peers

In case if there is no master peer associated
with a slave peer we have two cases

 - the master peer was closed before slave
 - we just have no master peer at all, but
   only slave one

This patch addresses only first case -- we open
fake master and hook slaves on it, then close it
immediately.

The second case will be addressed later.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 cr-restore.c  |    4 +++
 include/tty.h |    1 +
 tty.c         |   85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 88 insertions(+), 2 deletions(-)

diff --git a/cr-restore.c b/cr-restore.c
index 4ce2336..4f5089a 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -144,6 +144,10 @@ static int prepare_shared(void)
 		goto err;
 
 	mark_pipe_master();
+	ret = tty_setup_orphan_slavery(&opts);
+	if (ret)
+		goto err;
+
 
 	ret = tty_prepare_shared();
 	if (ret)
diff --git a/include/tty.h b/include/tty.h
index 2a8f746..dbb1856 100644
--- a/include/tty.h
+++ b/include/tty.h
@@ -17,5 +17,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_setup_orphan_slavery(const struct cr_options *opts);
 
 #endif /* CR_TTY_H__ */
diff --git a/tty.c b/tty.c
index 9a13598..1607b520 100644
--- a/tty.c
+++ b/tty.c
@@ -80,6 +80,8 @@ struct tty_info {
 
 	struct list_head		sibling;
 	int				major;
+
+	bool				create;
 };
 
 static LIST_HEAD(all_tty_info_entries);
@@ -520,6 +522,42 @@ static int receive_tty(struct tty_info *info)
 	return fd;
 }
 
+static int pty_open_fake_ptmx(struct tty_info *slave)
+{
+	int master = -1, ret = -1, fd = -1;
+	char pts_name[64];
+
+	snprintf(pts_name, sizeof(pts_name), PTS_FMT, slave->tie->pty->index);
+
+	master = pty_open_ptmx_index(O_RDONLY, slave->tie->pty->index);
+	if (master < 0) {
+		pr_perror("Can't open fale %x (index %d)",
+			  slave->tfe->id, slave->tie->pty->index);
+		return -1;
+	}
+
+	unlock_pty(master);
+
+	fd = open(pts_name, slave->tfe->flags);
+	if (fd < 0) {
+		pr_perror("Can't open slave %s", pts_name);
+		goto err;
+	}
+
+	if (restore_tty_params(fd, slave))
+		goto err;
+
+	if (pty_open_slaves(slave))
+		goto err;
+
+	ret = fd;
+	fd = -1;
+err:
+	close_safe(&master);
+	close_safe(&fd);
+	return ret;
+}
+
 static int pty_open_ptmx(struct tty_info *info)
 {
 	int master = -1;
@@ -567,9 +605,12 @@ static int tty_open(struct file_desc *d)
 
 	tty_show_pty_info("open", info);
 
-	if (!pty_is_master(info))
+	if (!info->create)
 		return receive_tty(info);
 
+	if (!pty_is_master(info))
+		return pty_open_fake_ptmx(info);
+
 	return pty_open_ptmx(info);
 
 }
@@ -577,7 +618,7 @@ static int tty_open(struct file_desc *d)
 static int tty_transport(FdinfoEntry *fe, struct file_desc *d)
 {
 	struct tty_info *info = container_of(d, struct tty_info, d);
-	return pty_is_master(info) == false;
+	return !info->create;
 }
 
 static struct file_desc_ops tty_desc_ops = {
@@ -607,6 +648,45 @@ static int tty_find_restoring_task(struct tty_info *info)
 	return -1;
 }
 
+int tty_setup_orphan_slavery(const struct cr_options *opts)
+{
+	struct tty_info *info, *peer, *m;
+
+	list_for_each_entry(info, &all_ttys, list) {
+		struct fdinfo_list_entry *a, *b;
+		bool has_leader = false;
+
+		if (pty_is_master(info))
+			continue;
+
+		a = file_master(&info->d);
+		m = info;
+
+		list_for_each_entry(peer, &info->sibling, sibling) {
+			if (pty_is_master(peer)) {
+				has_leader = true;
+				break;
+			}
+
+			b = file_master(&peer->d);
+			if (a->pid > b->pid ||
+			    (a->pid == b->pid && a->fe->fd > b->fe->fd)) {
+				a = b;
+				m = peer;
+			}
+		}
+
+		/* Here is new one */
+		if (!has_leader) {
+			m->create = true;
+			pr_debug("Found orphan slave fake leader (%#x)\n",
+				 m->tfe->id);
+		}
+	}
+
+	return 0;
+}
+
 static int tty_setup_slavery(void)
 {
 	struct tty_info *info, *peer, *m;
@@ -740,6 +820,7 @@ static int collect_one_tty(void *obj, ProtobufCMessage *msg)
 
 	INIT_LIST_HEAD(&info->sibling);
 	info->major = major(info->tie->rdev);
+	info->create = (info->major == TTYAUX_MAJOR);
 
 	if (verify_info(info))
 		return -1;
-- 
1.7.7.6



More information about the CRIU mailing list