[CRIU] [PATCH 3/3] tty: Restore unread data from the image

Cyrill Gorcunov gorcunov at openvz.org
Tue Apr 12 15:08:40 PDT 2016


Just read it from the image and write into appropriate peer.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 criu/cr-restore.c  |  1 +
 criu/include/tty.h |  1 +
 criu/tty.c         | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 82 insertions(+)

diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index 93dc5c91b197..f3c1566f5d18 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -178,6 +178,7 @@ static struct collect_image_info *cinfos[] = {
 	&fanotify_mark_cinfo,
 	&tty_info_cinfo,
 	&tty_cinfo,
+	&tty_cdata,
 	&tunfile_cinfo,
 	&ext_file_cinfo,
 	&timerfd_cinfo,
diff --git a/criu/include/tty.h b/criu/include/tty.h
index 0db3b764e585..7ed0895e7168 100644
--- a/criu/include/tty.h
+++ b/criu/include/tty.h
@@ -22,6 +22,7 @@ extern int tty_post_dump(int ret);
 extern int dump_verify_tty_sids(void);
 extern struct collect_image_info tty_info_cinfo;
 extern struct collect_image_info tty_cinfo;
+extern struct collect_image_info tty_cdata;
 extern int prepare_shared_tty(void);
 
 extern int tty_verify_active_pairs(void);
diff --git a/criu/tty.c b/criu/tty.c
index 42d218858923..8cb4570e65dc 100644
--- a/criu/tty.c
+++ b/criu/tty.c
@@ -78,6 +78,11 @@ struct tty_info_entry {
 	TtyInfoEntry			*tie;
 };
 
+struct tty_data_entry {
+	struct list_head		list;
+	TtyDataEntry			*tde;
+};
+
 struct tty_info {
 	struct list_head		list;
 	struct file_desc		d;
@@ -94,6 +99,8 @@ struct tty_info {
 	bool				inherit;
 
 	struct tty_info			*ctl_tty;
+	struct tty_info			*link;
+	struct tty_data_entry		*tty_data;
 };
 
 struct tty_dump_info {
@@ -112,6 +119,7 @@ struct tty_dump_info {
 	size_t				size;
 };
 
+static LIST_HEAD(all_tty_data_entries);
 static LIST_HEAD(all_tty_info_entries);
 static LIST_HEAD(all_ttys);
 
@@ -829,6 +837,14 @@ static int pty_open_slaves(struct tty_info *info)
 			goto err;
 		}
 
+		if (slave->link && slave->link->tty_data) {
+			ProtobufCBinaryData bd = slave->link->tty_data->tde->data;
+
+			pr_debug("restore queued data on master %#x (%zu bytes)\n",
+				 slave->link->tfe->id, (size_t)bd.len);
+			write(fd, bd.data, bd.len);
+		}
+
 		close(fd);
 		fd = -1;
 	}
@@ -966,6 +982,15 @@ static int pty_open_ptmx(struct tty_info *info)
 		}
 	}
 
+	if (info->link && info->link->tty_data) {
+		ProtobufCBinaryData bd = info->link->tty_data->tde->data;
+
+		pr_debug("restore queued data on slave %#x (%zu bytes)\n",
+			 info->link->tfe->id, (size_t)bd.len);
+
+		write(master, bd.data, bd.len);
+	}
+
 	if (pty_open_slaves(info))
 		goto err;
 
@@ -1228,11 +1253,46 @@ static int tty_setup_orphan_slavery(void)
 	return 0;
 }
 
+static struct tty_data_entry *tty_lookup_data(struct tty_info *info)
+{
+	struct tty_data_entry *td;
+
+	list_for_each_entry(td, &all_tty_data_entries, list) {
+		if (td->tde->tty_id == info->tie->id)
+			return td;
+	}
+
+	return NULL;
+}
+
 static int tty_setup_slavery(void * unused)
 {
 	struct tty_info *info, *peer, *m;
 
 	/*
+	 * Setup links for PTY terminal pairs.
+	 */
+	list_for_each_entry(info, &all_ttys, list) {
+		if (!is_pty(info->driver) || info->link)
+			continue;
+		peer = info;
+		list_for_each_entry_continue(peer, &all_ttys, list) {
+			if (!is_pty(peer->driver) || peer->link)
+				continue;
+			if (peer->tie->pty->index == info->tie->pty->index) {
+				info->link = peer;
+				peer->link = info;
+
+				pr_debug("Link PTYs (%#x)\n", info->tfe->id);
+
+				info->tty_data = tty_lookup_data(info);
+				peer->tty_data = tty_lookup_data(peer);
+				break;
+			}
+		}
+	}
+
+	/*
 	 * The image may carry several terminals opened
 	 * belonging to the same session, so choose the
 	 * leader which gonna be setting up the controlling
@@ -1423,6 +1483,8 @@ static int collect_one_tty(void *obj, ProtobufCMessage *msg, struct cr_img *i)
 	info->create = tty_is_master(info);
 	info->inherit = false;
 	info->ctl_tty = NULL;
+	info->tty_data = NULL;
+	info->link = NULL;
 
 	if (verify_info(info))
 		return -1;
@@ -1479,6 +1541,24 @@ struct collect_image_info tty_cinfo = {
 	.collect	= collect_one_tty,
 };
 
+static int collect_one_tty_data(void *obj, ProtobufCMessage *msg, struct cr_img *i)
+{
+	struct tty_data_entry *tdo = obj;
+
+	tdo->tde = pb_msg(msg, TtyDataEntry);
+	list_add(&tdo->list, &all_tty_data_entries);
+	pr_debug("Collected data for id %#x (size %zu bytes)\n",
+		 tdo->tde->tty_id, (size_t)tdo->tde->data.len);
+	return 0;
+}
+
+struct collect_image_info tty_cdata = {
+	.fd_type	= CR_FD_TTY_DATA,
+	.pb_type	= PB_TTY_DATA,
+	.priv_size	= sizeof(struct tty_data_entry),
+	.collect	= collect_one_tty_data,
+};
+
 /* Make sure the ttys we're dumping do belong our process tree */
 int dump_verify_tty_sids(void)
 {
-- 
2.5.5



More information about the CRIU mailing list