[Devel] [PATCH rh7 v2] vtty: Allow to wait until container's console appear

Vladimir Davydov vdavydov at virtuozzo.com
Fri Jun 10 08:05:04 PDT 2016


On Fri, Jun 10, 2016 at 04:34:34PM +0300, Cyrill Gorcunov wrote:
> After tty code redesing we've been requiring container to start
> first before be able to connect into it via vzctl console command.
> Here we rather allow userspace tool to wait until container brought
> to life and proceed connecting into console.
> 
> https://jira.sw.ru/browse/PSBM-39463
> 
> Note: when someone tried to open several consoles for offline
> mode (say vzctl console 300 1 and vzctl console 300 2) simultaneously
> only one is allowed until VE is up, the second vzctl command will
> exit with -EBUSY.
> 
> v2:
>  - move everything into vtty code
> 
> Signed-off-by: Cyrill Gorcunov <gorcunov at virtuozzo.com>
> CC: Vladimir Davydov <vdavydov at virtuozzo.com>
> CC: Konstantin Khorenko <khorenko at virtuozzo.com>
> CC: Igor Sukhih <igor at virtuozzo.com>
> CC: Pavel Emelyanov <xemul at virtuozzo.com>
> ---
>  drivers/tty/pty.c   |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/ve.h  |    2 +
>  kernel/ve/ve.c      |    5 +++
>  kernel/ve/vecalls.c |    6 ++--
>  4 files changed, 77 insertions(+), 3 deletions(-)
> 
> Index: linux-pcs7.git/drivers/tty/pty.c
> ===================================================================
> --- linux-pcs7.git.orig/drivers/tty/pty.c
> +++ linux-pcs7.git/drivers/tty/pty.c
> @@ -1284,8 +1284,64 @@ static int __init vtty_init(void)
>  	return 0;
>  }
>  
> +static DECLARE_RWSEM(vtty_console_sem);
> +static DEFINE_IDR(vtty_idr_console);

We already have vtty_idr, may be reuse it?

> +
> +static struct ve_struct *vtty_get_ve_by_id(envid_t veid)
> +{
> +	DECLARE_COMPLETION_ONSTACK(console_work);
> +	struct ve_struct *ve;
> +	int ret;
> +
> +	down_write(&vtty_console_sem);
> +	ve = get_ve_by_id(veid);
> +	if (ve) {
> +		up_write(&vtty_console_sem);
> +		return ve;
> +	}
> +

> +	if (idr_find(&vtty_idr_console, veid)) {
> +		up_write(&vtty_console_sem);
> +		return ERR_PTR(-EBUSY);
> +	}

This block is useless - it's handled by ENOSPC check below.

> +
> +	ret = idr_alloc(&vtty_idr_console, &console_work, veid, veid + 1, GFP_KERNEL);
> +	if (ret < 0) {
> +		if (ret == -ENOSPC)
> +			ret = -EBUSY;
> +	} else
> +		ret = 0;
> +	up_write(&vtty_console_sem);
> +
> +	if (!ret)
> +		ret = wait_for_completion_interruptible(&console_work);
> +
> +	if (!ret)
> +		ve = get_ve_by_id(veid);
> +	else
> +		ve = ERR_PTR(ret);
> +
> +	down_write(&vtty_console_sem);
> +	if (!ret)
> +		idr_remove(&vtty_idr_console, veid);
> +	up_write(&vtty_console_sem);
> +	return ve;
> +}
> +
> +void vtty_console_notify(struct ve_struct *ve)
> +{
> +	struct completion *console_work;
> +
> +	down_read(&vtty_console_sem);
> +	console_work = idr_find(&vtty_idr_console, ve->veid);
> +	if (console_work)
> +		complete(console_work);
> +	up_read(&vtty_console_sem);
> +}
> +
>  int vtty_open_master(envid_t veid, int idx)
>  {
> +	struct ve_struct *ve = NULL;
>  	struct tty_struct *tty;
>  	struct file *file;
>  	char devname[64];
> @@ -1298,6 +1354,16 @@ int vtty_open_master(envid_t veid, int i
>  	if (fd < 0)
>  		return fd;
>  
> +	ve = vtty_get_ve_by_id(veid);
> +	if (IS_ERR_OR_NULL(ve)) {
> +		if (IS_ERR(ve))
> +			ret = PTR_ERR(ve);
> +		else
> +			ret = -ENOENT;
> +		ve = NULL;
> +		goto err_put_unused_fd;
> +	}
> +

Come to think of it, is this really necessary? Can't we just allocate
vtty_map in vtty_open_master and return master tty w/o open slave? Any
write/read will put the caller to sleep anyway.

>  	snprintf(devname, sizeof(devname), "v%utty%d", veid, idx);
>  	file = anon_inode_getfile(devname, &vtty_fops, NULL, O_RDWR);
>  	if (IS_ERR(file)) {
> @@ -1364,6 +1430,7 @@ int vtty_open_master(envid_t veid, int i
>  	mutex_unlock(&tty_mutex);
>  	ret = fd;
>  out:
> +	put_ve(ve);
>  	return ret;
>  
>  err_install:
> Index: linux-pcs7.git/include/linux/ve.h
> ===================================================================
> --- linux-pcs7.git.orig/include/linux/ve.h
> +++ linux-pcs7.git/include/linux/ve.h
> @@ -215,6 +215,8 @@ void ve_stop_ns(struct pid_namespace *ns
>  void ve_exit_ns(struct pid_namespace *ns);
>  int ve_start_container(struct ve_struct *ve);
>  
> +void vtty_console_notify(struct ve_struct *ve);
> +
>  extern bool current_user_ns_initial(void);
>  struct user_namespace *ve_init_user_ns(void);
>  
> Index: linux-pcs7.git/kernel/ve/ve.c
> ===================================================================
> --- linux-pcs7.git.orig/kernel/ve/ve.c
> +++ linux-pcs7.git/kernel/ve/ve.c
> @@ -494,6 +494,11 @@ int ve_start_container(struct ve_struct
>  
>  	get_ve(ve); /* for ve_exit_ns() */
>  
> +	/*
> +	 * Console waiter are to be notified at the very
> +	 * end when everything else is ready.
> +	 */
> +	vtty_console_notify(ve);
>  	return 0;
>  
>  err_iterate:
> Index: linux-pcs7.git/kernel/ve/vecalls.c
> ===================================================================
> --- linux-pcs7.git.orig/kernel/ve/vecalls.c
> +++ linux-pcs7.git/kernel/ve/vecalls.c
> @@ -990,6 +990,9 @@ static int ve_configure(envid_t veid, un
>  	struct ve_struct *ve;
>  	int err = -ENOKEY;
>  
> +	if (key == VE_CONFIGURE_OPEN_TTY)
> +		return vtty_open_master(veid, val);
> +
>  	ve = get_ve_by_id(veid);
>  	if (!ve)
>  		return -EINVAL;
> @@ -998,9 +1001,6 @@ static int ve_configure(envid_t veid, un
>  	case VE_CONFIGURE_OS_RELEASE:
>  		err = init_ve_osrelease(ve, data);
>  		break;
> -	case VE_CONFIGURE_OPEN_TTY:
> -		err = vtty_open_master(ve->veid, val);
> -		break;
>  	}
>  
>  	put_ve(ve);


More information about the Devel mailing list