[CRIU] [PATCH 11/11] tty: Use regular files engine to save paths to the peers

Cyrill Gorcunov gorcunov at gmail.com
Mon Oct 6 12:01:08 PDT 2014


On Mon, Oct 06, 2014 at 05:15:50PM +0400, Cyrill Gorcunov wrote:
> Currently we're using predefined format for master/slave pty peers:
> masters are always /dev/ptmx, while slaves are /dev/pts/$index,
> where $index is the peer number.

Tycho, could you please apply first 10 patches from this series, but
insted of 11 use this one attached.
-------------- next part --------------
>From ff3b0a42ba7defc323dd608fc7629e4dc51b3f89 Mon Sep 17 00:00:00 2001
From: Cyrill Gorcunov <gorcunov at openvz.org>
Date: Mon, 6 Oct 2014 21:30:04 +0400
Subject: [PATCH] tty: Save pty peers paths in image

Currently we're using predefined format for master/slave pty peers:
masters are always /dev/ptmx, while slaves are /dev/pts/$index,
where $index is the peer number.

While fitting most of distros this is not always correct and slave peers
might be mounted to an arbitrary place, so that we need to somehow
carry paths with ourself in image.

Thus save paths to the pty peers in the image itself. Moreover
reserve place for @mnt_id and @dev_sb as well it will be needed
to support multiple pty instances.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 protobuf/tty.proto |   4 ++
 tty.c              | 164 ++++++++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 140 insertions(+), 28 deletions(-)

diff --git a/protobuf/tty.proto b/protobuf/tty.proto
index 8942965c580b..c3bfacfe5244 100644
--- a/protobuf/tty.proto
+++ b/protobuf/tty.proto
@@ -64,4 +64,8 @@ message tty_file_entry {
 
 	required uint32			flags		= 3;
 	required fown_entry		fown		= 4;
+
+	optional uint32			mnt_id		= 5;
+	optional uint32			dev_sb		= 6;
+	optional string			path		= 7;
 }
diff --git a/tty.c b/tty.c
index edbe85e7505a..34c9aeaab51d 100644
--- a/tty.c
+++ b/tty.c
@@ -24,6 +24,7 @@
 #include "util.h"
 #include "log.h"
 #include "list.h"
+#include "mount.h"
 #include "util-pie.h"
 #include "proc_parse.h"
 #include "file-ids.h"
@@ -86,6 +87,7 @@ struct tty_info {
 	struct list_head		sibling;
 	int				major;
 	int				minor;
+	char				*path;
 
 	bool				create;
 	bool				inherit;
@@ -123,6 +125,10 @@ static DECLARE_BITMAP(tty_active_pairs, (MAX_TTYS << 1));
  */
 static mutex_t *tty_mutex;
 
+static char *pty_alloc_path(struct tty_info *info, bool master);
+#define pty_alloc_path_master(info)	pty_alloc_path(info, true)
+#define pty_alloc_path_slave(info)	pty_alloc_path(info, false)
+
 int prepare_shared_tty(void)
 {
 	tty_mutex = shmalloc(sizeof(*tty_mutex));
@@ -245,7 +251,7 @@ static int tty_test_and_set(int bit, unsigned long *bitmap)
 	return ret;
 }
 
-static int pty_open_ptmx_index(int flags, int index)
+static int pty_open_ptmx_index(char *path, int flags, int index)
 {
 	int fds[32], i, ret = -1, cur_idx;
 
@@ -254,14 +260,14 @@ static int pty_open_ptmx_index(int flags, int index)
 	mutex_lock(tty_mutex);
 
 	for (i = 0; i < ARRAY_SIZE(fds); i++) {
-		fds[i] = open(PTMX_PATH, flags);
+		fds[i] = open(path, flags);
 		if (fds[i] < 0) {
-			pr_perror("Can't open %s", PTMX_PATH);
+			pr_perror("Can't open %s", path);
 			break;
 		}
 
 		if (ioctl(fds[i], TIOCGPTN, &cur_idx)) {
-			pr_perror("Can't obtain current index on %s", PTMX_PATH);
+			pr_perror("Can't obtain current index on %s", path);
 			break;
 		}
 
@@ -281,7 +287,7 @@ static int pty_open_ptmx_index(int flags, int index)
 		if (cur_idx < index && (index - cur_idx) < ARRAY_SIZE(fds))
 			continue;
 
-		pr_err("Unable to open %s with specified index %d\n", PTMX_PATH, index);
+		pr_err("Unable to open %s with specified index %d\n", path, index);
 		break;
 	}
 
@@ -347,15 +353,18 @@ static int tty_restore_ctl_terminal(struct file_desc *d, int fd)
 {
 	struct tty_info *info = container_of(d, struct tty_info, d);
 	int slave, ret = -1;
-	char pts_name[64];
+	char *pts_path;
 
 	if (!is_service_fd(fd, CTL_TTY_OFF))
 		return 0;
 
-	snprintf(pts_name, sizeof(pts_name), PTS_FMT, info->tie->pty->index);
-	slave = open(pts_name, O_RDONLY);
+	pts_path = pty_alloc_path_slave(info);
+	if (!pts_path)
+		return -1;
+	slave = open(pts_path, O_RDONLY);
 	if (slave < 0) {
-		pr_perror("Can't open %s", pts_name);
+		pr_perror("Can't open %s", pts_path);
+		xfree(pts_path);
 		return -1;
 	}
 
@@ -367,6 +376,7 @@ static int tty_restore_ctl_terminal(struct file_desc *d, int fd)
 	if (!ret)
 		ret = tty_set_prgp(slave, info->tie->pgrp);
 
+	xfree(pts_path);
 	close(slave);
 	close(fd);
 
@@ -458,9 +468,7 @@ static int pty_open_slaves(struct tty_info *info)
 	int sock = -1, fd = -1, ret = -1;
 	struct fdinfo_list_entry *fle;
 	struct tty_info *slave;
-	char pts_name[64];
-
-	snprintf(pts_name, sizeof(pts_name), PTS_FMT, info->tie->pty->index);
+	char *pts_path = NULL;
 
 	sock = socket(PF_UNIX, SOCK_DGRAM, 0);
 	if (sock < 0) {
@@ -468,12 +476,16 @@ static int pty_open_slaves(struct tty_info *info)
 		goto err;
 	}
 
+	pts_path = pty_alloc_path_slave(info);
+	if (!pts_path)
+		return -1;
+
 	list_for_each_entry(slave, &info->sibling, sibling) {
 		BUG_ON(tty_is_master(slave));
 
-		fd = open(pts_name, slave->tfe->flags | O_NOCTTY);
+		fd = open(pts_path, slave->tfe->flags | O_NOCTTY);
 		if (fd < 0) {
-			pr_perror("Can't open slave %s", pts_name);
+			pr_perror("Can't open slave %s", pts_path);
 			goto err;
 		}
 
@@ -483,7 +495,7 @@ static int pty_open_slaves(struct tty_info *info)
 		fle = file_master(&slave->d);
 
 		pr_debug("send slave %#x fd %d connected on %s (pid %d)\n",
-			 slave->tfe->id, fd, pts_name, fle->pid);
+			 slave->tfe->id, fd, pts_path, fle->pid);
 
 		if (send_fd_to_peer(fd, fle, sock)) {
 			pr_perror("Can't send file descriptor");
@@ -496,6 +508,7 @@ static int pty_open_slaves(struct tty_info *info)
 	ret = 0;
 
 err:
+	xfree(pts_path);
 	close_safe(&fd);
 	close_safe(&sock);
 	return ret;
@@ -525,6 +538,7 @@ static int receive_tty(struct tty_info *info)
 static int pty_open_unpaired_slave(struct file_desc *d, struct tty_info *slave)
 {
 	int master = -1, ret = -1, fd = -1;
+	char *ptmx_path = NULL;
 
 	/*
 	 * We may have 2 cases here: the slave either need to
@@ -540,22 +554,25 @@ static int pty_open_unpaired_slave(struct file_desc *d, struct tty_info *slave)
 		pr_info("Migrated slave peer %x -> to fd %d\n",
 			slave->tfe->id, fd);
 	} else {
-		char pts_name[64];
-
-		snprintf(pts_name, sizeof(pts_name), PTS_FMT, slave->tie->pty->index);
+		ptmx_path = pty_alloc_path_master(slave);
+		if (!ptmx_path)
+			goto err;
 
-		master = pty_open_ptmx_index(O_RDONLY, slave->tie->pty->index);
+		master = pty_open_ptmx_index(ptmx_path,
+					     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;
+			pr_perror("Can't open fake %s (id %#x index %d)",
+				  ptmx_path, slave->tfe->id,
+				  slave->tie->pty->index);
+			goto err;
 		}
 
 		unlock_pty(master);
 
-		fd = open(pts_name, slave->tfe->flags | O_NOCTTY);
+		fd = open(slave->path, slave->tfe->flags | O_NOCTTY);
 		if (fd < 0) {
-			pr_perror("Can't open slave %s", pts_name);
+			pr_perror("Can't open slave %s", slave->path);
 			goto err;
 		}
 
@@ -597,18 +614,26 @@ static int pty_open_unpaired_slave(struct file_desc *d, struct tty_info *slave)
 err:
 	close_safe(&master);
 	close_safe(&fd);
+	xfree(ptmx_path);
 	return ret;
 }
 
 static int pty_open_ptmx(struct tty_info *info)
 {
+	char *ptmx_path = NULL;
 	int master = -1;
 
-	master = pty_open_ptmx_index(info->tfe->flags, info->tie->pty->index);
-	if (master < 0) {
-		pr_perror("Can't open %x (index %d)",
-			  info->tfe->id, info->tie->pty->index);
+	ptmx_path = pty_alloc_path_master(info);
+	if (!ptmx_path)
 		return -1;
+
+	master = pty_open_ptmx_index(ptmx_path,
+				     info->tfe->flags,
+				     info->tie->pty->index);
+	if (master < 0) {
+		pr_perror("Can't open %s (id %#x index %d)",
+			  ptmx_path, info->tfe->id, info->tie->pty->index);
+		goto err;
 	}
 
 	unlock_pty(master);
@@ -635,9 +660,11 @@ static int pty_open_ptmx(struct tty_info *info)
 	if (info->tie->locked)
 		lock_pty(master);
 
+	xfree(ptmx_path);
 	return master;
 err:
 	close_safe(&master);
+	xfree(ptmx_path);
 	return -1;
 }
 
@@ -951,6 +978,66 @@ struct collect_image_info tty_info_cinfo = {
 	.flags		= COLLECT_OPTIONAL,
 };
 
+static int tty_make_path(struct tty_info *info)
+{
+	if (info->tfe->path) {
+		info->path = &info->tfe->path[1];
+		return 0;
+	}
+
+	if (tty_is_master(info))
+		info->path = xstrdup("/dev/ptmx");
+	else {
+		info->path = xmalloc(64);
+		if (info->path) {
+			snprintf(info->path, 64, "/dev/pts/%u",
+				 info->tie->pty->index);
+		}
+	}
+
+	if (!info->path)
+		return -1;
+	return 0;
+}
+
+static char *pty_alloc_path(struct tty_info *info, bool master)
+{
+	char *pos, *path;
+	size_t len, slash_at;
+
+	if ((tty_is_master(info) && master) ||
+	    (!tty_is_master(info) && !master))
+		return xstrdup(info->path);
+
+	len = strlen(info->path) + 1;
+	pos = strrchr(info->path, '/');
+	slash_at = pos - info->path;
+
+	if (!pos) {
+		pr_err("Malformed path %s for %#x\n",
+		       info->path, info->tfe->id);
+		return NULL;
+	}
+
+	path = xmalloc(len + 32);
+	if (!path)
+		return NULL;
+
+	memcpy(path, info->path, slash_at);
+	if (master) {
+		strcat(path, "ptmx");
+	} else {
+		if (slash_at >= 4 && strcmp(&path[slash_at - 4], "pts"))
+			snprintf(&path[slash_at], 10,
+				 "/pts/%u", info->tie->pty->index);
+		else
+			snprintf(&path[slash_at], 10,
+				 "/%u", info->tie->pty->index);
+	}
+
+	return path;
+}
+
 static int collect_one_tty(void *obj, ProtobufCMessage *msg)
 {
 	struct tty_info *info = obj;
@@ -973,6 +1060,9 @@ static int collect_one_tty(void *obj, ProtobufCMessage *msg)
 	if (verify_info(info))
 		return -1;
 
+	if (tty_make_path(info))
+		return -1;
+
 	/*
 	 * The tty peers which have no @termios are hung up,
 	 * so don't mark them as active, we create them with
@@ -1174,6 +1264,24 @@ static int dump_one_pty(int lfd, u32 id, const struct fd_parms *p, int major, in
 	e.flags		= p->flags;
 	e.fown		= (FownEntry *)&p->fown;
 
+	e.has_dev_sb	= true;
+	e.dev_sb	= p->stat.st_dev;
+	e.path		= p->link->name;
+
+	e.has_mnt_id	= true;
+	if (p->mnt_id != -1) {
+		e.mnt_id = p->mnt_id;
+	} else {
+		struct mount_info *m = lookup_mnt_sdev(p->stat.st_dev);
+		if (!m) {
+			pr_err("Can't find mount with st_dev %#x\n",
+			       (int)p->stat.st_dev);
+			return -1;
+		}
+
+		e.mnt_id = m->mnt_id;
+	}
+
 	/*
 	 * FIXME
 	 *
-- 
1.9.3



More information about the CRIU mailing list