[CRIU] [PATCH] tty: add vt support

Ruslan Kuprieiev kupruser at gmail.com
Fri Dec 5 03:06:07 PST 2014


Thanks for reviewing this patch!

I've tested it by running all tests from a tty (they
fail without this patch), by c/r-ing task running
on some tty as a shell-job and by c/r-ing "openvt prog",
which runs prog on the first available tty as a session
leader.

Not sure what test to add to zdtm. Will console-like
test where we mknod(path, flags, makedev(major, minor))
be enough?

Thanks.

On 12/05/2014 11:05 AM, Cyrill Gorcunov wrote:
> On Fri, Dec 05, 2014 at 01:44:22AM +0200, Ruslan Kuprieiev wrote:
>> /dev/ttyN are the virtual terminals which are provided
>> by the system with major 4 and minor 0..63.
>> You can run some program on ttyN by pressing alt+ctrl+FN
>> and running it manualy or by using open(openvt nowadays).
>>
>> Signed-off-by: Ruslan Kuprieiev <kupruser at gmail.com>
>> ---
>>   include/tty.h      |  9 ++++++++
>>   protobuf/tty.proto |  1 +
>>   tty.c              | 62 ++++++++++++++++++++++++++++++++++++++++++++----------
>>   3 files changed, 61 insertions(+), 11 deletions(-)
>>
>> diff --git a/include/tty.h b/include/tty.h
>> index a3026f6..5019dcf 100644
>> --- a/include/tty.h
>> +++ b/include/tty.h
>> @@ -13,6 +13,7 @@ enum {
>>   	TTY_TYPE_PTM		= 1,
>>   	TTY_TYPE_PTS		= 2,
>>   	TTY_TYPE_CONSOLE	= 3,
>> +	TTY_TYPE_VT		= 4,
>>
>>   	TTY_TYPE_MAX
>>   };
>> @@ -34,6 +35,14 @@ static inline int tty_type(int major, int minor)
>>   		else if (minor == 1)
>>   			return TTY_TYPE_CONSOLE;
>>   		break;
>> +	case TTY_MAJOR:
>> +		if (minor < 64)
>> +			/*
>> +			 * Beyond 63 are the serial devices.
>> +			 * Not sure how to handle them, so lets
>> +			 * leave them till someone requests.
>> +			 */
>> +			return TTY_TYPE_VT;
>
> This should be something like that
>
> 			/*
> 			 * Minors [1; MAX_NR_CONSOLES] stand for
> 			 * consoles (virtual terminals, VT in terms
> 			 * of kernel).
> 			 */
>
> Also MAX_NR_CONSOLES is defined in uapi/vt.h thus we should inlcude it
> directly
>
> #include <linux/vt.h>
>
> or (if this is a problem for some reason -- predefine own MAX_NR_CONSOLES).
>
>>   	case UNIX98_PTY_MASTER_MAJOR ... (UNIX98_PTY_MASTER_MAJOR + UNIX98_PTY_MAJOR_COUNT - 1):
>>   		return TTY_TYPE_PTM;
>>   	case UNIX98_PTY_SLAVE_MAJOR:
>> diff --git a/protobuf/tty.proto b/protobuf/tty.proto
>> index 18470a9..0e67e85 100644
>> --- a/protobuf/tty.proto
>> +++ b/protobuf/tty.proto
>> @@ -27,6 +27,7 @@ enum TtyType {
>>   	UNKNOWN		= 0;
>>   	PTY		= 1;
>>   	CONSOLE		= 2;
>> +	VT		= 3;
>>   }
>>
>>   message tty_info_entry {
>> diff --git a/tty.c b/tty.c
>> index b076f06..5886dff 100644
>> --- a/tty.c
>> +++ b/tty.c
>> @@ -118,6 +118,7 @@ static LIST_HEAD(all_ttys);
>>   #define MAX_TTYS	1024
>>   #define MAX_PTY_INDEX	1000
>>   #define CONSOLE_INDEX	1002
>> +#define VT_INDEX	1004
>>
>>   static DECLARE_BITMAP(tty_bitmap, (MAX_TTYS << 1));
>>   static DECLARE_BITMAP(tty_active_pairs, (MAX_TTYS << 1));
>> @@ -235,11 +236,17 @@ static int parse_tty_index(u32 id, int lfd, const struct fd_parms *p, int type)
>>   	case TTY_TYPE_CONSOLE:
>>   		index = CONSOLE_INDEX;
>>   		break;
>> +
>> +	case TTY_TYPE_VT: {
>> +		index = VT_INDEX;
>> +		break;
>> +	}
>
> Redundant { } here
>
>>   	default:
>>   		BUG();
>>   	}
>>
>>   	if (type != TTY_TYPE_CONSOLE &&
>> +	    type != TTY_TYPE_VT &&
>>   	    index > MAX_PTY_INDEX) {
>>   		pr_err("Index %d on tty %x is too big\n", index, id);
>>   		return -1;
>> @@ -508,6 +515,13 @@ static int tty_restore_ctl_terminal(struct file_desc *d, int fd)
>>   			pr_perror("Can't open %s", path_from_reg(info->reg_d));
>>   			goto err;
>>   		}
>> +	} else if (info->type == TTY_TYPE_VT) {
>> +		slave = open_pty_reg(info->reg_d, O_RDONLY);
>> +		index = VT_INDEX;
>> +		if (slave < 0) {
>> +			pr_perror("Can't open %s", path_from_reg(info->reg_d));
>> +			goto err;
>> +		}
>>   	} else
>>   		BUG();
>>
>> @@ -534,13 +548,21 @@ static char *tty_name(int type)
>>   		return "pts";
>>   	case TTY_TYPE_CONSOLE:
>>   		return "console";
>> +	case TTY_TYPE_VT:
>> +		return "tty";
>>   	}
>>   	return "unknown";
>>   }
>>
>>   static bool tty_is_master(struct tty_info *info)
>>   {
>> -	return info->type == TTY_TYPE_PTM || info->type == TTY_TYPE_CONSOLE;
>> +	if (info->type == TTY_TYPE_PTM || info->type == TTY_TYPE_CONSOLE)
>> +		return true;
>> +
>> +	if (info->type == TTY_TYPE_VT && !opts.shell_job)
>> +		return true;
>> +
>> +	return false;
>>   }
>>
>>   static bool tty_is_hung(struct tty_info *info)
>> @@ -558,9 +580,21 @@ static bool tty_has_active_pair(struct tty_info *info)
>>
>>   static void tty_show_pty_info(char *prefix, struct tty_info *info)
>>   {
>> +	int index;
>
> 	int index = -1;
>
>> +
>> +	switch (info->type) {
>> +	case TTY_TYPE_CONSOLE:
>> +		index = CONSOLE_INDEX;
>> +		break;
>> +	case TTY_TYPE_VT:
>> +		index = VT_INDEX;
>> +		break;
>
> 	case TTY_TYPE_PTM:
> 	case TTY_TYPE_PTS:
> 		index = info->tie->pty->index;
> 		break;
>
>> +	default:
>> +		index = info->tie->pty->index;
>> +	}
>
> drop this "default"
>
>> +
>>   	pr_info("%s type %s id %#x index %d (master %d sid %d pgrp %d inherit %d)\n",
>> -		prefix, tty_name(info->type), info->tfe->id,
>> -		info->type == TTY_TYPE_CONSOLE ? CONSOLE_INDEX : info->tie->pty->index,
>> +		prefix, tty_name(info->type), info->tfe->id, index,
>>   		tty_is_master(info), info->tie->sid, info->tie->pgrp, info->inherit);
>>   }
>>
>> @@ -788,14 +822,15 @@ err:
>>   	return -1;
>>   }
>>
>> -static int open_console(struct tty_info *info)
>> +static int open_simple_tty(struct tty_info *info)
>>   {
>>   	int fd = -1;
>>
>>   	fd = open_pty_reg(info->reg_d, info->tfe->flags);
>>   	if (fd < 0) {
>> -		pr_perror("Can't open console %x",
>> -			  info->tfe->id);
>> +		pr_perror("Can't open %s %x",
>> +		info->type == TTY_TYPE_CONSOLE ? "console" : "virtual terminal",
>> +		info->tfe->id);
>>   		return -1;
>>   	}
>>
>> @@ -820,8 +855,8 @@ static int tty_open(struct file_desc *d)
>>   	if (!tty_is_master(info))
>>   		return pty_open_unpaired_slave(d, info);
>>
>> -	if (info->type == TTY_TYPE_CONSOLE)
>> -		return open_console(info);
>> +	if (info->type == TTY_TYPE_CONSOLE || info->type == TTY_TYPE_VT)
>> +		return open_simple_tty(info);
>
> This should be somehow cleaned up, I'll think on it, but lets leave it as
> in patch for now
>
>>
>>   	return pty_open_ptmx(info);
>>   }
>> @@ -1002,12 +1037,12 @@ int tty_setup_slavery(void)
>>   	list_for_each_entry(info, &all_ttys, list) {
>>   		if (tty_find_restoring_task(info))
>>   			return -1;
>> -		if (info->type == TTY_TYPE_CONSOLE)
>> +		if (info->type == TTY_TYPE_CONSOLE || info->type == TTY_TYPE_VT)
>>   			continue;
>>
>>   		peer = info;
>>   		list_for_each_entry_safe_continue(peer, m, &all_ttys, list) {
>> -			if (peer->type == TTY_TYPE_CONSOLE)
>> +			if (peer->type == TTY_TYPE_CONSOLE || info->type == TTY_TYPE_VT)
>>   				continue;
>>   			if (peer->tie->pty->index != info->tie->pty->index)
>>   				continue;
>> @@ -1057,7 +1092,8 @@ static int verify_info(struct tty_info *info)
>>   {
>>   	if (info->type != TTY_TYPE_PTM &&
>>   	    info->type != TTY_TYPE_PTS &&
>> -	    info->type != TTY_TYPE_CONSOLE) {
>> +	    info->type != TTY_TYPE_CONSOLE &&
>> +	    info->type != TTY_TYPE_VT) {
>>   		pr_err("Unknown type %d master peer %x\n",
>>   		       info->type, info->tfe->id);
>>   		return -1;
>> @@ -1115,6 +1151,7 @@ static int collect_one_tty_info_entry(void *obj, ProtobufCMessage *msg)
>>   		}
>>   		break;
>>   	case TTY_TYPE__CONSOLE:
>> +	case TTY_TYPE__VT:
>>   		if (info->tie->pty) {
>>   			pr_err("PTY data found (id %x), corrupted image?\n",
>>   			       info->tie->id);
>> @@ -1312,6 +1349,9 @@ static int dump_tty_info(int lfd, u32 id, const struct fd_parms *p, int type, in
>>   	case TTY_TYPE_CONSOLE:
>>   		info.type	= TTY_TYPE__CONSOLE;
>>   		break;
>> +	case TTY_TYPE_VT:
>> +		info.type	= TTY_TYPE__VT;
>> +		break;
>>   	default:
>>   		BUG();
>>   	}
>
> The rest looks good to me, hopefully it works as needed (some zdtm tests?).
> But I didn't look into kernel implementatio so might be missing something.
>
> 	Cyrill
>



More information about the CRIU mailing list