[Devel] [PATCH rh7] tty: vzcon -- Add container dummy console support

Cyrill Gorcunov gorcunov at virtuozzo.com
Tue Jun 16 03:18:24 PDT 2015


In PCS6 we have a console emulation via virtual tty code
(VTTY option in config file). The code of vtty is very
close to standart pty (unix98 terminals) but on new kernels
the pty code has been heavily modified due to changes in
tty layer itself.

That said this vz console is rather a simple stub for future
enhancements which zaps messages written to it by the kernel
but allows systemd based conatiners (such as Fedora 21)
to successfully hook agetty service on the conatiner's console.

https://jira.sw.ru/browse/PSBM-32686

Signed-off-by: Cyrill Gorcunov <gorcunov at virtuozzo.com>
CC: Andrey Vagin <avagin at virtuozzo.com>
CC: Vladimir Davydov <vdavydov at virtuozzo.com>
CC: Konstantin Khorenko <khorenko at virtuozzo.com>
CC: Pavel Emelyanov <xemul at virtuozzo.com>
---

I'm gonna enhance it and make fully functional tty link
(we don't need all 12 lines in console as it were in pcs6,
 frankly I don't even have an idea why it was so in first
 place. Moreover there should not be veid reference in
 devices as it were in pcs6, we're switching to UUID
 based scheme so the VE should report itself where
 virtualized console slave peer will be avalable. I think
 I put it into one of ve/ cgroup file instead).

Meanwhile with this patch we can run systemd based containers
and internal agetty service won't complain.

 drivers/tty/tty_io.c |    6 +-
 kernel/ve/Makefile   |    2 
 kernel/ve/console.c  |  146 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 151 insertions(+), 3 deletions(-)

Index: linux-pcs7.git/drivers/tty/tty_io.c
===================================================================
--- linux-pcs7.git.orig/drivers/tty/tty_io.c
+++ linux-pcs7.git/drivers/tty/tty_io.c
@@ -1941,10 +1941,12 @@ static struct tty_driver *tty_lookup_dri
 #endif
 	case MKDEV(TTYAUX_MAJOR, 1): {
 		struct tty_driver *console_driver = console_device(index);
+#ifdef CONFIG_VE
 		if (!ve_is_super(get_exec_env())) {
-			printk_once("Support of virtual console is not yet implemented in VE\n");
-			return ERR_PTR(-ENODEV);
+			extern struct tty_driver *vz_console_device(int *index);
+			console_driver = vz_console_device(index);
 		}
+#endif
 		if (console_driver) {
 			driver = tty_driver_kref_get(console_driver);
 			if (driver) {
Index: linux-pcs7.git/kernel/ve/Makefile
===================================================================
--- linux-pcs7.git.orig/kernel/ve/Makefile
+++ linux-pcs7.git/kernel/ve/Makefile
@@ -4,7 +4,7 @@
 # Copyright (c) 2000-2015 Parallels IP Holdings GmbH
 #
 
-obj-$(CONFIG_VE) = ve.o veowner.o hooks.o vzstat_core.o ve-kobject.o
+obj-$(CONFIG_VE) = ve.o veowner.o hooks.o vzstat_core.o ve-kobject.o console.o
 obj-$(CONFIG_VZ_WDOG) += vzwdog.o
 obj-$(CONFIG_VE_CALLS) += vzmon.o
 
Index: linux-pcs7.git/kernel/ve/console.c
===================================================================
--- /dev/null
+++ linux-pcs7.git/kernel/ve/console.c
@@ -0,0 +1,146 @@
+#define pr_fmt(fmt) "vz con: " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/console.h>
+#include <linux/anon_inodes.h>
+#include <linux/file.h>
+#include <linux/tty.h>
+#include <linux/ve.h>
+
+static struct tty_driver *vz_con_driver;
+
+struct vz_tty_priv {
+	struct tty_port		port;
+	struct ve_struct	*owner_ve;
+};
+
+static int vz_tty_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+	static const struct tty_port_operations vz_tty_port_ops;
+	struct vz_tty_priv *priv;
+	int ret;
+
+	BUG_ON(tty->index != 0);
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->owner_ve = get_exec_env();
+	tty_port_init(&priv->port);
+	priv->port.ops = &vz_tty_port_ops;
+	tty->driver_data = priv;
+
+	ret = tty_port_install(&priv->port, driver, tty);
+	if (ret) {
+		pr_err("Can't install tty port: %d\n", ret);
+		goto err;
+	}
+
+	return 0;
+err:
+	tty_port_destroy(&priv->port);
+	kfree(priv);
+	return ret;
+}
+
+static int vz_tty_open(struct tty_struct *tty, struct file *filp)
+{
+	struct vz_tty_priv *priv = tty->driver_data;
+	return tty_port_open(&priv->port, tty, filp);
+}
+
+static void vz_tty_close(struct tty_struct *tty, struct file *filp)
+{
+	struct vz_tty_priv *priv = tty->driver_data;
+	tty_port_close(&priv->port, tty, filp);
+}
+
+static void vz_tty_cleanup(struct tty_struct *tty)
+{
+	struct vz_tty_priv *priv = tty->driver_data;
+
+	tty->driver_data = NULL;
+	priv->owner_ve = NULL;
+	tty_port_destroy(&priv->port);
+	kfree(priv);
+}
+
+static int vz_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
+{
+	return count;
+}
+
+static int vz_tty_write_room(struct tty_struct *tty)
+{
+	return 4096;
+}
+
+static void vz_tty_hangup(struct tty_struct *tty)
+{
+	struct vz_tty_priv *priv = tty->driver_data;
+	tty_port_hangup(&priv->port);
+}
+
+static const struct tty_operations vz_tty_fops = {
+	.install	= vz_tty_install,
+	.open		= vz_tty_open,
+	.close		= vz_tty_close,
+	.cleanup	= vz_tty_cleanup,
+	.write		= vz_tty_write,
+	.write_room	= vz_tty_write_room,
+	.hangup		= vz_tty_hangup,
+};
+
+static void __exit vz_exit(void)
+{
+	put_tty_driver(vz_con_driver);
+}
+module_exit(vz_exit)
+
+static int __init init(void)
+{
+	int ret = 0;
+
+	vz_con_driver = tty_alloc_driver(1,
+					 TTY_DRIVER_REAL_RAW		|
+					 TTY_DRIVER_RESET_TERMIOS	|
+					 TTY_DRIVER_CONTAINERIZED);
+	if (IS_ERR(vz_con_driver)) {
+		pr_err("Couldn't allocate vzcon driver\n");
+		return PTR_ERR(vz_con_driver);
+	}
+
+	vz_con_driver->driver_name	= "vzcon driver";
+	vz_con_driver->name		= "vzcon";
+	vz_con_driver->name_base	= 1;
+	vz_con_driver->major		= 0;
+	vz_con_driver->minor_start	= 1;
+	vz_con_driver->type		= TTY_DRIVER_TYPE_CONSOLE;
+	vz_con_driver->init_termios	= tty_std_termios;
+	vz_con_driver->ve		= get_ve0();
+	tty_set_operations(vz_con_driver, &vz_tty_fops);
+
+	ret = tty_register_driver(vz_con_driver);
+	if (ret) {
+		pr_err("Couldn't register vzcon driver\n");
+		put_tty_driver(vz_con_driver);
+		return ret;
+	}
+
+	return 0;
+}
+module_init(init);
+
+struct tty_driver *vz_console_device(int *index)
+{
+	*index = 0;
+	return vz_con_driver;
+}
+EXPORT_SYMBOL(vz_console_device);
+
+MODULE_DESCRIPTION("VZ conatiner console");
+MODULE_LICENSE("GPL v2");



More information about the Devel mailing list