[CRIU] [PATCH 3/5] tty: allow to dump and restore external terminals (v2)

Andrey Vagin avagin at openvz.org
Fri Dec 25 06:49:35 PST 2015


From: Andrew Vagin <avagin at virtuozzo.com>

Now we can use the --inherit-fd option to mark external terminals on dump
and to tell which file desdriptors should be used to restore these terminals.

Here is an example how it works:
$ setsid sleep 1000

$ ipython
In [1]: import os
In [2]: st = os.stat("/proc/self/fd/0")
In [3]: print "tty[%x:%x]" % (st.st_rdev, st.st_dev)
tty:[8800:d]

$ps -C sleep
  PID TTY          TIME CMD
 4109 ?        00:00:00 sleep

$ ./criu dump --inherit-fd 'fd:tty[8800:d]' -D imgs -v4 -t 4109
$ ./criu restore --inherit-fd 'fd[1]:tty[8800:d]' -D imgs -v4

v2: add missed break
    remove @non_file from tty_driver

Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
---
 crtools.c          |  4 +++-
 files.c            |  2 +-
 include/files.h    |  1 +
 protobuf/tty.proto |  1 +
 tty.c              | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 5 files changed, 62 insertions(+), 6 deletions(-)

diff --git a/crtools.c b/crtools.c
index 1e547c7..7e69239 100644
--- a/crtools.c
+++ b/crtools.c
@@ -772,7 +772,9 @@ usage:
 "  --enable-fs FSNAMES   a comma separated list of filesystem names or \"all\".\n"
 "                        force criu to (try to) dump/restore these filesystem's\n"
 "                        mountpoints even if fs is not supported.\n"
-"  --external RES        dump objects from this list as external resources\n"
+"  --external RES        dump objects from this list as external resources:\n"
+"                        Formats of RES:\n"
+"                            tty[rdev:dev]\n"
 "\n"
 "* Logging:\n"
 "  -o|--log-file FILE    log file name\n"
diff --git a/files.c b/files.c
index 3b51af2..db7ae84 100644
--- a/files.c
+++ b/files.c
@@ -1451,7 +1451,7 @@ void inherit_fd_log(void)
 /*
  * Look up the inherit fd list by a file identifier.
  */
-static int inherit_fd_lookup_id(char *id)
+int inherit_fd_lookup_id(char *id)
 {
 	int ret;
 	struct inherit_fd *inh;
diff --git a/include/files.h b/include/files.h
index 56de89d..b4ae8ef 100644
--- a/include/files.h
+++ b/include/files.h
@@ -176,6 +176,7 @@ extern int inherit_fd_resolve_clash(int fd);
 extern int inherit_fd_fini(void);
 
 extern bool external_lookup_id(char *id);
+extern int inherit_fd_lookup_id(char *id);
 
 extern bool inherited_fd(struct file_desc *, int *fdp);
 
diff --git a/protobuf/tty.proto b/protobuf/tty.proto
index fce5e79..4b5a70c 100644
--- a/protobuf/tty.proto
+++ b/protobuf/tty.proto
@@ -30,6 +30,7 @@ enum TtyType {
 	CONSOLE		= 2;
 	VT		= 3;
 	CTTY		= 4;
+	EXT_TTY		= 5;
 }
 
 message tty_info_entry {
diff --git a/tty.c b/tty.c
index 7e666e6..a38de47 100644
--- a/tty.c
+++ b/tty.c
@@ -203,6 +203,13 @@ static struct tty_driver vt_driver = {
 	.open			= open_simple_tty,
 };
 
+static int open_ext_tty(struct tty_info *info);
+static struct tty_driver ext_driver = {
+	.type			= TTY_TYPE__EXT_TTY,
+	.name			= "ext",
+	.open			= open_ext_tty,
+};
+
 static int pts_fd_get_index(int fd, const struct fd_parms *p)
 {
 	int index;
@@ -235,6 +242,11 @@ static struct tty_driver pts_driver = {
 struct tty_driver *get_tty_driver(dev_t rdev, dev_t dev)
 {
 	int major, minor;
+	char id[42];
+
+	snprintf(id, sizeof(id), "tty[%lx:%lx]", rdev, dev);
+	if (external_lookup_id(id) || inherit_fd_lookup_id(id) >= 0)
+		return &ext_driver;
 
 	major = major(rdev);
 	minor = minor(rdev);
@@ -606,6 +618,12 @@ static int tty_restore_ctl_terminal(struct file_desc *d, int fd)
 	if (!is_service_fd(fd, CTL_TTY_OFF))
 		return 0;
 
+	if (driver->type == TTY_TYPE__EXT_TTY) {
+		slave = -1;
+		if (!inherited_fd(&info->d, &slave) && slave < 0)
+			return -1;
+		goto out;
+	}
 	if (driver->img_get_index)
 		index = driver->img_get_index(info);
 	else
@@ -626,6 +644,7 @@ static int tty_restore_ctl_terminal(struct file_desc *d, int fd)
 		goto err;
 	}
 
+out:
 	pr_info("Restore session %d by %d tty (index %d)\n",
 		 info->tie->sid, (int)getpid(), index);
 
@@ -652,6 +671,9 @@ static bool tty_is_master(struct tty_info *info)
 	case TTY_TYPE__VT:
 		if (!opts.shell_job)
 			return true;
+		break;
+	case TTY_TYPE__EXT_TTY:
+		return true;
 	}
 
 	return false;
@@ -970,6 +992,21 @@ err:
 	return -1;
 }
 
+static int open_ext_tty(struct tty_info *info)
+{
+	int fd = -1;
+
+	if (!inherited_fd(&info->d, &fd) && fd < 0)
+		return -1;
+
+	if (restore_tty_params(fd, info)) {
+		close(fd);
+		return -1;
+	}
+
+	return fd;
+}
+
 static int tty_open(struct file_desc *d)
 {
 	struct tty_info *info = container_of(d, struct tty_info, d);
@@ -1013,12 +1050,22 @@ static void tty_collect_fd(struct file_desc *d, struct fdinfo_list_entry *fle,
 	list_add_tail(&fle->ps_list, tgt);
 }
 
+static char *tty_d_name(struct file_desc *d, char *buf, size_t s)
+{
+	struct tty_info *info = container_of(d, struct tty_info, d);
+
+	snprintf(buf, s, "tty[%x:%x]", info->tie->rdev, info->tie->dev);
+
+	return buf;
+}
+
 static struct file_desc_ops tty_desc_ops = {
 	.type		= FD_TYPES__TTY,
 	.open		= tty_open,
 	.post_open	= tty_restore_ctl_terminal,
 	.want_transport = tty_transport,
 	.collect_fd	= tty_collect_fd,
+	.name		= tty_d_name,
 };
 
 static struct pstree_item *find_first_sid(int sid)
@@ -1322,6 +1369,7 @@ static int collect_one_tty_info_entry(void *obj, ProtobufCMessage *msg)
 	case TTY_TYPE__CTTY:
 	case TTY_TYPE__CONSOLE:
 	case TTY_TYPE__VT:
+	case TTY_TYPE__EXT_TTY:
 		if (info->tie->pty) {
 			pr_err("PTY data found (id %x), corrupted image?\n",
 			       info->tie->id);
@@ -1362,6 +1410,10 @@ static int collect_one_tty(void *obj, ProtobufCMessage *msg)
 
 	INIT_LIST_HEAD(&info->sibling);
 	info->driver = get_tty_driver(info->tie->rdev, info->tie->dev);
+	if (info->driver == NULL) {
+		pr_err("Unable to find a tty driver\n");
+		return -1;
+	}
 	info->create = tty_is_master(info);
 	info->inherit = false;
 	info->ctl_tty = NULL;
@@ -1383,7 +1435,7 @@ static int collect_one_tty(void *obj, ProtobufCMessage *msg)
 				       info->tfe->id);
 				return -1;
 			}
-		} else {
+		} if (info->driver->type != TTY_TYPE__EXT_TTY) {
 			pr_err("No reg_d descriptor for id %#x\n", info->tfe->id);
 			return -1;
 		}
@@ -1585,9 +1637,6 @@ static int dump_one_tty(int lfd, u32 id, const struct fd_parms *p)
 
 	pr_info("Dumping tty %d with id %#x\n", lfd, id);
 
-	if (dump_one_reg_file(lfd, id, p))
-		return -1;
-
 	driver = get_tty_driver(p->stat.st_rdev, p->stat.st_dev);
 	if (driver->fd_get_index)
 		index = driver->fd_get_index(lfd, p);
@@ -1599,6 +1648,9 @@ static int dump_one_tty(int lfd, u32 id, const struct fd_parms *p)
 		return -1;
 	}
 
+	if (driver->type != TTY_TYPE__EXT_TTY && dump_one_reg_file(lfd, id, p))
+		return -1;
+
 	e.id		= id;
 	e.tty_info_id	= tty_gen_id(driver, index);
 	e.flags		= p->flags;
-- 
2.4.3



More information about the CRIU mailing list