[CRIU] [PATCH 11/12] tty: Add external ttys handling

Andrew Vagin avagin at parallels.com
Fri Oct 3 01:00:30 PDT 2014


On Fri, Oct 03, 2014 at 11:50:04AM +0400, Cyrill Gorcunov wrote:
> Some types of ttys (such as /dev/console) should be c/r'ed in
> simle manner -- just opent them by path on restore, for this
> sake that named external TTYs are introduced.
> 
> For example, for /dev/console one simply need to pass an option
> 
> 	--ext-tty 5:1

Can we use paths instead of maj:min? For example LXC bindmounts a host
/dev/pty/X to /dev/console.

> 
> where 5 represent major number of console and 1 is a minor, and
> the criu will simply re-open it on restore.
> 
> This should be enough for the start.
> 
> Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
> ---
>  Documentation/criu.txt |   9 ++
>  crtools.c              |  10 +-
>  files.c                |  10 ++
>  include/tty.h          |  14 ++
>  protobuf/tty.proto     |   6 +
>  tty.c                  | 344 +++++++++++++++++++++++++++++++++++++++++++------
>  6 files changed, 350 insertions(+), 43 deletions(-)
> 
> diff --git a/Documentation/criu.txt b/Documentation/criu.txt
> index a1296f9b5bdc..4656d2cbea96 100644
> --- a/Documentation/criu.txt
> +++ b/Documentation/criu.txt
> @@ -124,6 +124,15 @@ OPTIONS
>      VAL is the path on host that will be bind-mounted into container
>      (to the mountpoint path from image)
>  
> +*-T*, *--ext-tty* 'major'*:*'minor'::
> +    Define device with 'major':'minor' as external tty. Also ranges of
> +    device numbers are allowed in form of a-b:c-d.
> +
> +    For such devices on restore only basic properties are saved into
> +    the image file including a path to the external tty.
> +
> +    On restore it simply get opened by path.
> +
>  *--action-script* 'SCRIPT'::
>      Add an external action script.
>      The environment variable *CRTOOLS_SCRIPT_ACTION* contains one of the
> diff --git a/crtools.c b/crtools.c
> index b8f73060222f..4a9bb0ba6e0a 100644
> --- a/crtools.c
> +++ b/crtools.c
> @@ -28,6 +28,7 @@
>  #include "files.h"
>  #include "sk-inet.h"
>  #include "net.h"
> +#include "tty.h"
>  #include "version.h"
>  #include "page-xfer.h"
>  #include "tty.h"
> @@ -133,7 +134,7 @@ int main(int argc, char *argv[], char *envp[])
>  	int log_level = LOG_UNSET;
>  	char *imgs_dir = ".";
>  	char *work_dir = NULL;
> -	static const char short_opts[] = "dSsRf:F:t:p:hcD:o:n:v::xVr:jlW:L:M:";
> +	static const char short_opts[] = "dSsRf:F:t:p:hcD:o:n:v::xVr:jlW:L:M:T:";
>  	static struct option long_opts[] = {
>  		{ "tree", required_argument, 0, 't' },
>  		{ "pid", required_argument, 0, 'p' },
> @@ -174,6 +175,7 @@ int main(int argc, char *argv[], char *envp[])
>  		{ "cpu-cap", required_argument, 0, 1057},
>  		{ "force-irmap", no_argument, 0, 1058},
>  		{ "ext-mount-map", required_argument, 0, 'M'},
> +		{ "ext-tty", required_argument, 0, 'T'},
>  		{ "exec-cmd", no_argument, 0, 1059},
>  		{ "manage-cgroups", no_argument, 0, 1060},
>  		{ "cgroup-root", required_argument, 0, 1061},
> @@ -395,6 +397,10 @@ int main(int argc, char *argv[], char *envp[])
>  					return 1;
>  			}
>  			break;
> +		case 'T':
> +			if (tty_add_ext(optarg))
> +				return 1;
> +			break;
>  		case 'V':
>  			pr_msg("Version: %s\n", CRIU_VERSION);
>  			if (strcmp(CRIU_GITID, "0"))
> @@ -576,6 +582,8 @@ usage:
>  "  --force-irmap         force resolving names for inotify/fsnotify watches\n"
>  "  -M|--ext-mount-map KEY:VALUE\n"
>  "                        add external mount mapping\n"
> +"  -T|--ext-tty major:minor\n"
> +"                        add external tty device\n"
>  "  --manage-cgroups      dump or restore cgroups the process is in\n"
>  "  --cgroup-root [controller:]/newroot\n"
>  "                        change the root cgroup the controller will be\n"
> diff --git a/files.c b/files.c
> index b975cd46d011..df523014a9b0 100644
> --- a/files.c
> +++ b/files.c
> @@ -33,6 +33,7 @@
>  #include "signalfd.h"
>  #include "namespaces.h"
>  #include "tun.h"
> +#include "tty.h"
>  #include "timerfd.h"
>  #include "imgset.h"
>  #include "fs-magic.h"
> @@ -286,11 +287,20 @@ static int dump_chrdev(struct fd_parms *p, int lfd, struct cr_img *img)
>  	default: {
>  		char more[32];
>  
> +		/*
> +		 * Ext mapping for tty devices.
> +		 */
> +		if (lookup_ext_tty(maj, minor(p->stat.st_rdev))) {
> +			ops = &tty_dump_ops;
> +			goto found;
> +		}
> +
>  		sprintf(more, "%d:%d", maj, minor(p->stat.st_rdev));
>  		return dump_unsupp_fd(p, lfd, img, "chr", more);
>  	}
>  	}
>  
> +found:
>  	return do_dump_gen_file(p, lfd, ops, img);
>  }
>  
> diff --git a/include/tty.h b/include/tty.h
> index d2c31e298a34..f7ce4eab4b75 100644
> --- a/include/tty.h
> +++ b/include/tty.h
> @@ -3,6 +3,17 @@
>  
>  #include "files.h"
>  
> +typedef struct {
> +	struct {
> +		unsigned int from;
> +		unsigned int to;
> +	} major;
> +	struct {
> +		unsigned int from;
> +		unsigned int to;
> +	} minor;
> +} ext_tty_range_t;
> +
>  /* Kernel's limit */
>  #define TERMIOS_NCC	19
>  
> @@ -26,4 +37,7 @@ extern void tty_fini_fds(void);
>  
>  #define OPT_SHELL_JOB	"shell-job"
>  
> +extern ext_tty_range_t *lookup_ext_tty(unsigned int major, unsigned int minor);
> +extern int tty_add_ext(char *opt);
> +
>  #endif /* __CR_TTY_H__ */
> diff --git a/protobuf/tty.proto b/protobuf/tty.proto
> index 215bff35f212..4e842503c3e1 100644
> --- a/protobuf/tty.proto
> +++ b/protobuf/tty.proto
> @@ -24,9 +24,14 @@ message tty_pty_entry {
>  	optional uint32			mnt_id		= 2;
>  }
>  
> +message tty_ext_entry {
> +	required string			path		= 1;
> +};
> +
>  enum TtyType {
>  	UNKNOWN		= 0;
>  	PTY		= 1;
> +	EXT		= 2;
>  }
>  
>  message tty_info_entry {
> @@ -57,6 +62,7 @@ message tty_info_entry {
>  	 * TTY type.
>  	 */
>  	optional tty_pty_entry		pty		= 12;
> +	optional tty_ext_entry		ext		= 13;
>  };
>  
>  message tty_file_entry {
> diff --git a/tty.c b/tty.c
> index 497bb4a775df..029849333bf9 100644
> --- a/tty.c
> +++ b/tty.c
> @@ -104,7 +104,8 @@ struct tty_dump_info {
>  };
>  
>  static LIST_HEAD(all_tty_info_entries);
> -static LIST_HEAD(all_ttys);
> +static LIST_HEAD(all_ptys);
> +static LIST_HEAD(all_ext);
>  
>  /*
>   * Usually an application has not that many ttys opened.
> @@ -119,11 +120,111 @@ static DECLARE_BITMAP(tty_bitmap, (MAX_TTYS << 1));
>  static DECLARE_BITMAP(tty_active_pairs, (MAX_TTYS << 1));
>  
>  /*
> + * External ttys tracking.
> + */
> +static ext_tty_range_t ext_tty_ranges[64];
> +static size_t nr_ext_tty_ranges;
> +static unsigned int ext_tty_ids = (MAX_TTYS << 1) + 2;
> +
> +/*
>   * /dev/ptmx is a shared resource between all tasks
>   * so we need to serialize access to it.
>   */
>  static mutex_t *tty_mutex;
>  
> +/*
> + * Expect "a[-b]:c[-d],e[-f]:g[-h]" format here
> + */
> +int tty_add_ext(char *optarg)
> +{
> +	char *opts, *tok;
> +
> +#define __push_ext_tty_different_pair(__which, __from, __to)			\
> +	do {									\
> +		ext_tty_ranges[nr_ext_tty_ranges].__which.from = __from;	\
> +		ext_tty_ranges[nr_ext_tty_ranges].__which.to = __to;		\
> +	} while (0)
> +
> +#define __push_ext_tty_same_pair(__which, __num)				\
> +	do {									\
> +		ext_tty_ranges[nr_ext_tty_ranges].__which.from =		\
> +		ext_tty_ranges[nr_ext_tty_ranges].__which.to = __num;		\
> +	} while (0)
> +
> +	opts = xstrdup(optarg);
> +	if (!opts)
> +		return -1;
> +	if (strchr(opts, ','))
> +		tok = strtok(opts, ",");
> +	else
> +		tok = opts;
> +
> +	do {
> +		char *d = strchr(tok, ':');
> +		char *m;
> +
> +		if (nr_ext_tty_ranges == ARRAY_SIZE(ext_tty_ranges) - 1)
> +			goto Eoverflow;
> +
> +		if (!d || d == tok || d == (tok + strlen(tok) - 1))
> +			goto Esyntax;
> +
> +		*d = '\0';
> +		m = strchr(tok, '-');
> +		if (m) {
> +			if (m == tok || m == (tok + strlen(tok) - 1))
> +				goto Esyntax;
> +			*m = '\0';
> +			__push_ext_tty_different_pair(major, atoi(tok),  atoi(m + 1));
> +		} else {
> +			__push_ext_tty_same_pair(major, atoi(tok));
> +		}
> +
> +		tok = d + 1;
> +		m = strchr(tok, '-');
> +		if (m) {
> +			if (m == tok || m == (tok + strlen(tok) - 1))
> +				goto Esyntax;
> +			*m = '\0';
> +			__push_ext_tty_different_pair(minor, atoi(tok),  atoi(m + 1));
> +		} else {
> +			__push_ext_tty_same_pair(minor, atoi(tok));
> +		}
> +		nr_ext_tty_ranges++;
> +	} while ((tok = strtok(NULL, ",")));
> +
> +	xfree(opts);
> +	return 0;
> +
> +Esyntax:
> +	pr_err("Unknown format `%s' selected (expected 'a[-b]:c[-d],e[-f]:g[-h],...')\n", optarg);
> +	goto err;
> +Eoverflow:
> +	pr_err("Too many external tty maps are selected, "
> +	       "only %li is availabe\n", ARRAY_SIZE(ext_tty_ranges));
> +	goto err;
> +err:
> +	xfree(opts);
> +	return -1;
> +#undef __push_ext_tty_different_pair
> +#undef __push_ext_tty_same_pair
> +}
> +
> +ext_tty_range_t *lookup_ext_tty(unsigned int major, unsigned int minor)
> +{
> +	size_t i;
> +
> +	for (i = 0; i < nr_ext_tty_ranges; i++) {
> +		if (major < ext_tty_ranges[i].major.from	||
> +		    major > ext_tty_ranges[i].major.to		||
> +		    minor < ext_tty_ranges[i].minor.from	||
> +		    minor > ext_tty_ranges[i].minor.to)
> +			continue;
> +		return &ext_tty_ranges[i];
> +	}
> +	return NULL;
> +}
> +
>  int prepare_shared_tty(void)
>  {
>  	tty_mutex = shmalloc(sizeof(*tty_mutex));
> @@ -455,9 +556,13 @@ static bool tty_has_active_pair(struct tty_info *info)
>  
>  static void tty_show_pty_info(char *prefix, struct tty_info *info)
>  {
> -	pr_info("%s type %s id %#x index %d (master %d sid %d pgrp %d inherit %d)\n",
> -		prefix, tty_type(info->major, info->minor), info->tfe->id, info->tie->pty->index,
> -		tty_is_master(info), info->tie->sid, info->tie->pgrp, info->inherit);
> +	if (info->tie->type == TTY_TYPE__PTY)
> +		pr_info("%s type %s id %#x index %d (master %d sid %d pgrp %d inherit %d)\n",
> +			prefix, tty_type(info->major, info->minor), info->tfe->id, info->tie->pty->index,
> +			tty_is_master(info), info->tie->sid, info->tie->pgrp, info->inherit);
> +	else
> +		pr_info("%s type ext id %#x (path %s)\n",
> +			prefix, info->tfe->id, info->tie->ext->path);
>  }
>  
>  static int restore_tty_params(int fd, struct tty_info *info)
> @@ -691,6 +796,27 @@ err:
>  	return -1;
>  }
>  
> +static int tty_open_ext(struct file_desc *d, struct tty_info *info)
> +{
> +	int ret = -1, fd;
> +
> +	fd = open(info->tie->ext->path, info->tfe->flags | O_NOCTTY);
> +	if (fd < 0) {
> +		pr_perror("Can't open ext tty %s for fd %d",
> +			  info->tie->ext->path, fd);
> +		return -1;
> +	}
> +
> +	if (restore_tty_params(fd, info))
> +		goto err;
> +
> +	ret = fd;
> +	fd = -1;
> +err:
> +	close_safe(&fd);
> +	return ret;
> +}
> +
>  static int tty_open(struct file_desc *d)
>  {
>  	struct tty_info *info = container_of(d, struct tty_info, d);
> @@ -700,11 +826,14 @@ static int tty_open(struct file_desc *d)
>  	if (!info->create)
>  		return receive_tty(info);
>  
> -	if (!tty_is_master(info))
> -		return pty_open_unpaired_slave(d, info);
> -
> -	return pty_open_ptmx(info);
> -
> +	if (info->tie->type == TTY_TYPE__PTY) {
> +		if (!tty_is_master(info))
> +			return pty_open_unpaired_slave(d, info);
> +		return pty_open_ptmx(info);
> +	} else if (info->tie->type == TTY_TYPE__EXT)
> +		return tty_open_ext(d, info);
> +	BUG();
> +	return -1;
>  }
>  
>  static int tty_transport(FdinfoEntry *fe, struct file_desc *d)
> @@ -716,6 +845,7 @@ static int tty_transport(FdinfoEntry *fe, struct file_desc *d)
>  static void tty_collect_fd(struct file_desc *d, struct fdinfo_list_entry *fle,
>  		struct rst_info *ri)
>  {
> +	struct tty_info *info = container_of(d, struct tty_info, d);
>  	struct list_head *tgt;
>  
>  	/*
> @@ -723,7 +853,7 @@ static void tty_collect_fd(struct file_desc *d, struct fdinfo_list_entry *fle,
>  	 * opened before them
>  	 */
>  
> -	if (tty_is_master(container_of(d, struct tty_info, d)))
> +	if (tty_is_master(info) || info->tie->type == TTY_TYPE__EXT)
>  		tgt = &ri->fds;
>  	else
>  		tgt = &ri->tty_slaves;
> @@ -838,7 +968,7 @@ static int tty_setup_orphan_slavery(void)
>  {
>  	struct tty_info *info, *peer, *m;
>  
> -	list_for_each_entry(info, &all_ttys, list) {
> +	list_for_each_entry(info, &all_ptys, list) {
>  		struct fdinfo_list_entry *a, *b;
>  		bool has_leader = false;
>  
> @@ -880,12 +1010,12 @@ int tty_setup_slavery(void)
>  {
>  	struct tty_info *info, *peer, *m;
>  
> -	list_for_each_entry(info, &all_ttys, list) {
> +	list_for_each_entry(info, &all_ptys, list) {
>  		if (tty_find_restoring_task(info))
>  			return -1;
>  
>  		peer = info;
> -		list_for_each_entry_safe_continue(peer, m, &all_ttys, list) {
> +		list_for_each_entry_safe_continue(peer, m, &all_ptys, list) {
>  			if (peer->tie->pty->index != info->tie->pty->index)
>  				continue;
>  
> @@ -900,7 +1030,7 @@ int tty_setup_slavery(void)
>  	/*
>  	 * Print out information about peers.
>  	 */
> -	list_for_each_entry(info, &all_ttys, list) {
> +	list_for_each_entry(info, &all_ptys, list) {
>  		tty_show_pty_info("head", info);
>  		list_for_each_entry(peer, &info->sibling, sibling)
>  			tty_show_pty_info("    `- sibling", peer);
> @@ -951,8 +1081,15 @@ static int verify_info(struct tty_info *info)
>  	    verify_termios(info->tfe->id, info->tie->termios))
>  		return -1;
>  
> -	if (info->tie->termios && info->tfe->tty_info_id > (MAX_TTYS << 1))
> -		return -1;
> +	if (info->tie->type == TTY_TYPE__PTY) {
> +		if (info->tie->termios) {
> +			if (info->tfe->tty_info_id > (MAX_TTYS << 1)) {
> +				pr_err("Index %d is too big on %x\n",
> +				       info->tfe->tty_info_id, info->tfe->id);
> +				return -1;
> +			}
> +		}
> +	}
>  
>  	return 0;
>  }
> @@ -975,18 +1112,27 @@ static int collect_one_tty_info_entry(void *obj, ProtobufCMessage *msg)
>  
>  	info->tie = pb_msg(msg, TtyInfoEntry);
>  
> -	if (info->tie->type != TTY_TYPE__PTY) {
> -		pr_err("Unexpected TTY type %d (id %x)\n",
> +	switch (info->tie->type) {
> +	case TTY_TYPE__PTY:
> +		if (!info->tie->pty) {
> +			pr_err("No PTY data found (id %x), corrupted image?\n",
> +			       info->tie->id);
> +			return -1;
> +		}
> +		break;
> +	case TTY_TYPE__EXT:
> +		if (!info->tie->ext || !info->tie->ext->path) {
> +			pr_err("No EXT data found (id %x), corrupted image?\n",
> +			       info->tie->id);
> +			return -1;
> +		}
> +		break;
> +	default:
> +		pr_err("Unknown type %d (id %x), corrupted image?\n",
>  		       info->tie->type, info->tie->id);
>  		return -1;
>  	}
>  
> -	if (!info->tie->pty) {
> -		pr_err("No PTY data found (id %x), corrupted image?\n",
> -		       info->tie->id);
> -		return -1;
> -	}
> -
>  	INIT_LIST_HEAD(&info->list);
>  	list_add(&info->list, &all_tty_info_entries);
>  
> @@ -1017,25 +1163,34 @@ static int collect_one_tty(void *obj, ProtobufCMessage *msg)
>  	INIT_LIST_HEAD(&info->sibling);
>  	info->major = major(info->tie->rdev);
>  	info->minor = minor(info->tie->rdev);
> -	info->create = tty_is_master(info);
>  	info->inherit = false;
>  
>  	if (verify_info(info))
>  		return -1;
>  
> -	/*
> -	 * The tty peers which have no @termios are hung up,
> -	 * so don't mark them as active, we create them with
> -	 * faked master and they are rather a rudiment which
> -	 * can't be used. Most likely they appear if a user has
> -	 * dumped program when it was closing a peer.
> -	 */
> -	if (info->tie->termios)
> -		tty_test_and_set(info->tfe->tty_info_id, tty_active_pairs);
> +	switch (info->tie->type) {
> +	case TTY_TYPE__PTY:
> +		info->create = tty_is_master(info);
> +		list_add(&info->list, &all_ptys);
> +		/*
> +		 * The tty peers which have no @termios are hung up,
> +		 * so don't mark them as active, we create them with
> +		 * faked master and they are rather a rudiment which
> +		 * can't be used. Most likely they appear if a user has
> +		 * dumped program when it was closing a peer.
> +		 */
> +		if (info->tie->termios)
> +			tty_test_and_set(info->tfe->tty_info_id, tty_active_pairs);
> +		break;
> +	case TTY_TYPE__EXT:
> +		info->create = true;
> +		list_add(&info->list, &all_ext);
> +		break;
> +	default:
> +		BUG();
> +	}
>  
>  	pr_info("Collected tty ID %#x\n", info->tfe->id);
> -
> -	list_add(&info->list, &all_ttys);
>  	return file_desc_add(&info->d, info->tfe->id, &tty_desc_ops);
>  }
>  
> @@ -1071,7 +1226,7 @@ int dump_verify_tty_sids(void)
>  	 * In this case we simply zap sid/pgid and inherit
>  	 * the peer from the current terminal on restore.
>  	 */
> -	list_for_each_entry_safe(dinfo, n, &all_ttys, list) {
> +	list_for_each_entry_safe(dinfo, n, &all_ptys, list) {
>  		if (!ret && dinfo->sid) {
>  			struct pstree_item *item = find_first_sid(dinfo->sid);
>  
> @@ -1137,7 +1292,7 @@ static int dump_pty_info(int lfd, u32 id, const struct fd_parms *p, const struct
>  	dinfo->major		= major;
>  	dinfo->minor		= minor;
>  
> -	list_add_tail(&dinfo->list, &all_ttys);
> +	list_add_tail(&dinfo->list, &all_ptys);
>  
>  	info.id			= id;
>  	info.type		= TTY_TYPE__PTY;
> @@ -1270,10 +1425,110 @@ static int dump_one_pty(int lfd, u32 id, const struct fd_parms *p, int major, in
>  	return ret;
>  }
>  
> +static int dump_ext_tty(int lfd, u32 id, const struct fd_parms *p, int major, int minor)
> +{
> +	TtyFileEntry e			= TTY_FILE_ENTRY__INIT;
> +	TtyInfoEntry info		= TTY_INFO_ENTRY__INIT;
> +	TermiosEntry termios		= TERMIOS_ENTRY__INIT;
> +	TermiosEntry termios_locked	= TERMIOS_ENTRY__INIT;
> +	WinsizeEntry winsize		= WINSIZE_ENTRY__INIT;
> +	TtyExtEntry ety			= TTY_EXT_ENTRY__INIT;
> +
> +	struct termios t;
> +	struct winsize w;
> +
> +	ext_tty_range_t *ext;
> +	char path[PATH_MAX];
> +	char link[32];
> +	int len;
> +
> +	int ret = -1;
> +
> +	ext = lookup_ext_tty(major, minor);
> +	if (!ext)
> +		return -1;
> +
> +	pr_debug("External tty (%d:%d) matched (%u-%u|%u-%u)\n",
> +		 major, minor, ext->major.from, ext->major.to,
> +		 ext->minor.from, ext->minor.to);
> +
> +	snprintf(link, sizeof(link), "/proc/self/fd/%d", lfd);
> +	len = readlink(link, path, sizeof(path) - 1);
> +	if (len < 0) {
> +		pr_perror("Can't readlink %s", link);
> +		return -1;
> +	}
> +	path[len] = '\0';
> +
> +	e.id		= id;
> +	e.tty_info_id	= ext_tty_ids++;
> +	e.flags		= p->flags;
> +	e.fown		= (FownEntry *)&p->fown;
> +
> +	/*
> +	 * FIXME Merge with dump_pty_info()
> +	 */
> +	BUILD_BUG_ON(ARRAY_SIZE(t.c_cc) < TERMIOS_NCC);
> +	BUILD_BUG_ON(sizeof(termios.c_cc) != sizeof(void *));
> +	BUILD_BUG_ON((sizeof(termios.c_cc) * TERMIOS_NCC) < sizeof(t.c_cc));
> +
> +	info.id			= e.tty_info_id;
> +	info.type		= TTY_TYPE__EXT;
> +	info.sid		= 0;
> +	info.pgrp		= 0;
> +	info.rdev		= p->stat.st_rdev;
> +	info.termios		= &termios;
> +	info.termios_locked	= &termios_locked;
> +	info.winsize		= &winsize;
> +	info.ext		= &ety;
> +
> +	ety.path		= path;
> +
> +	termios.n_c_cc		= TERMIOS_NCC;
> +	termios.c_cc		= xmalloc(pb_repeated_size(&termios, c_cc));
> +
> +	termios_locked.n_c_cc	= TERMIOS_NCC;
> +	termios_locked.c_cc	= xmalloc(pb_repeated_size(&termios_locked, c_cc));
> +
> +	if (!termios.c_cc || !termios_locked.c_cc)
> +		goto out;
> +
> +	memzero(&t, sizeof(t));
> +	if (ioctl(lfd, TCGETS, &t) < 0) {
> +		pr_perror("Can't get tty params on %x", id);
> +		goto out;
> +	}
> +	termios_copy(&termios, &t);
> +
> +	memzero(&t, sizeof(t));
> +	if (ioctl(lfd, TIOCGLCKTRMIOS, &t) < 0) {
> +		pr_perror("Can't get tty locked params on %x", id);
> +		goto out;
> +	}
> +	termios_copy(&termios_locked, &t);
> +
> +	memzero(&w, sizeof(w));
> +	if (ioctl(lfd, TIOCGWINSZ, &w) < 0) {
> +		pr_perror("Can't get tty window params on %x", id);
> +		goto out;
> +	}
> +	winsize_copy(&winsize, &w);
> +
> +	ret = pb_write_one(img_from_set(glob_imgset, CR_FD_TTY_INFO), &info, PB_TTY_INFO);
> +
> +	if (!ret)
> +		ret = pb_write_one(img_from_set(glob_imgset, CR_FD_TTY_FILES), &e, PB_TTY_FILE);
> +out:
> +	xfree(termios.c_cc);
> +	xfree(termios_locked.c_cc);
> +	return ret;
> +}
> +
>  static int dump_one_tty(int lfd, u32 id, const struct fd_parms *p)
>  {
>  	int major = major(p->stat.st_rdev);
>  	int minor = minor(p->stat.st_rdev);
> +	int ret = -1;
>  
>  	pr_info("Dumping tty (%d:%d) %d with id %#x\n",
>  		major, minor, lfd, id);
> @@ -1281,17 +1536,22 @@ static int dump_one_tty(int lfd, u32 id, const struct fd_parms *p)
>  	switch (major) {
>  	case TTYAUX_MAJOR:
>  		if (minor == 0 || minor == 2)
> -			return dump_one_pty(lfd, id, p, major, minor);
> +			ret = dump_one_pty(lfd, id, p, major, minor);
> +		else
> +			ret = dump_ext_tty(lfd, id, p, major, minor);
>  		break;
>  	case UNIX98_PTY_MASTER_MAJOR ... (UNIX98_PTY_MASTER_MAJOR + UNIX98_PTY_MAJOR_COUNT - 1):
>  	case UNIX98_PTY_SLAVE_MAJOR:
> -		return dump_one_pty(lfd, id, p, major, minor);
> +		ret = dump_one_pty(lfd, id, p, major, minor);
> +		break;
>  	default:
> +		ret = dump_ext_tty(lfd, id, p, major, minor);
>  		break;
>  	}
>  
> -	pr_err("Unsupported tty (%d:%d) device\n", major, minor);
> -	return -1;
> +	if (ret)
> +		pr_err("Unsupported tty (%d:%d) device\n", major, minor);
> +	return ret;
>  }
>  
>  const struct fdtype_ops tty_dump_ops = {
> -- 
> 1.9.3
> 


More information about the CRIU mailing list