[Devel] [PATCH rh7] ve/tty: vt -- Add dummy stubs

Cyrill Gorcunov gorcunov at virtuozzo.com
Thu Jun 25 10:53:29 PDT 2015


It turns out that centos 6 based templates are using mingetty to listen
for login and such but we don't have virtual terminal virtualization
implemented yet (this gonna be addressed later). So because of this
we don't have /dev/ttyX devices present inside container fs which
make mingetty unhappy and force it to respawn in endless cycle.

Lets add stub code which allows to open up to 12 virtual
terminals but any write into them goes to /dev/nil, so
mingetty runs one instance of self and hangin around
doing nothing.

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

Signed-off-by: Cyrill Gorcunov <gorcunov at virtuozzo.com>
CC: Vladimir Davydov <vdavydov at virtuozzo.com>
CC: Konstantin Khorenko <khorenko at virtuozzo.com>
CC: Pavel Emelyanov <xemul at virtuozzo.com>
CC: Igor Sukhih <igor at parallels.com>
---

To igor@: please add "c 4:[0...12] rwm" into allowed devices for container cgroup.
Otherwise mingetty won't get access to these terminals. Actually I allowed 4:*
manually for testing purpose.

 drivers/tty/tty_io.c |   10 +++
 include/linux/ve.h   |    4 +
 kernel/ve/console.c  |  129 +++++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 140 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
@@ -1929,6 +1929,15 @@ static struct tty_driver *tty_lookup_dri
 {
 	struct tty_driver *driver;
 
+#ifdef CONFIG_VE
+	extern struct tty_driver *vz_vt_device(struct ve_struct *ve, dev_t dev, int *index);
+	if (!ve_is_super(get_exec_env()) &&
+	    (MAJOR(device) == TTY_MAJOR && MINOR(device) < VZ_VT_MAX_DEVS)) {
+		driver = tty_driver_kref_get(vz_vt_device(get_exec_env(), device, index));
+		*noctty = 1;
+		return driver;
+	}
+#endif
 	switch (device) {
 #ifdef CONFIG_VT
 	case MKDEV(TTY_MAJOR, 0): {
@@ -3090,6 +3099,7 @@ static struct class tty_class_base = {
 };
 
 struct class *tty_class = &tty_class_base;
+EXPORT_SYMBOL(tty_class);
 
 #ifdef CONFIG_VE
 static inline bool tty_handle_register(struct tty_driver *driver)
Index: linux-pcs7.git/include/linux/ve.h
===================================================================
--- linux-pcs7.git.orig/include/linux/ve.h
+++ linux-pcs7.git/include/linux/ve.h
@@ -66,6 +66,10 @@ struct ve_struct {
 	struct binfmt_misc	*binfmt_misc;
 #endif
 
+#define VZ_VT_MAX_DEVS		12
+	struct tty_driver	*vz_vt_driver;
+	struct tty_struct	*vz_tty_vt[VZ_VT_MAX_DEVS];
+
 	struct tty_struct	*vz_tty_conm;
 	struct tty_struct	*vz_tty_cons;
 
Index: linux-pcs7.git/kernel/ve/console.c
===================================================================
--- linux-pcs7.git.orig/kernel/ve/console.c
+++ linux-pcs7.git/kernel/ve/console.c
@@ -17,6 +17,8 @@
 static struct tty_driver *vz_conm_driver;
 static struct tty_driver *vz_cons_driver;
 
+extern struct class *tty_class;
+
 static char *vzcon_devnode(struct device *dev, umode_t *mode)
 {
 	if (mode)
@@ -122,6 +124,112 @@ static const struct tty_operations vz_tt
 	.unthrottle	= vz_tty_unthrottle,
 };
 
+static struct tty_struct *vz_vt_lookup(struct tty_driver *driver,
+				       struct inode *inode, int idx)
+{
+	struct ve_struct *ve = driver->ve;
+	return driver->ttys[idx];
+}
+
+static int vz_vt_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+	struct ve_struct *ve = driver->ve;
+
+	tty->port = kzalloc(sizeof(*tty->port), GFP_KERNEL);
+	if (!tty->port)
+		return -ENOMEM;
+	tty_standard_install(driver, tty);
+	tty_port_init(tty->port);
+	return 0;
+}
+
+static void vz_vt_cleanup(struct tty_struct *tty)
+{
+	kfree(tty->port);
+	tty->port = NULL;
+}
+
+const static struct tty_operations vt_tty_fops = {
+	.lookup		= vz_vt_lookup,
+	.install	= vz_vt_install,
+	.open		= vz_tty_open,
+	.cleanup	= vz_vt_cleanup,
+	.write		= vz_tty_write,
+	.write_room	= vz_tty_write_room,
+	.unthrottle	= vz_tty_unthrottle,
+};
+
+static int __vz_vt_ve_init(struct ve_struct *ve)
+{
+#define TTY_DRIVER_ALLOC_FLAGS			\
+	(TTY_DRIVER_REAL_RAW		|	\
+	 TTY_DRIVER_RESET_TERMIOS	|	\
+	 TTY_DRIVER_DYNAMIC_DEV		|	\
+	 TTY_DRIVER_CONTAINERIZED)
+
+	struct tty_driver *driver;
+	int ret = 0;
+	int i;
+
+	driver = tty_alloc_driver(VZ_VT_MAX_DEVS, TTY_DRIVER_ALLOC_FLAGS);
+	if (IS_ERR(driver)) {
+		ret = PTR_ERR(driver);
+		pr_err("Can't allocate VT master driver\n");
+		return ret;
+	}
+
+	driver->driver_name	= "vt_master";
+	driver->name		= "tty";
+	driver->name_base	= 1;
+	driver->major		= 0;
+	driver->minor_start	= 1;
+	driver->type		= TTY_DRIVER_TYPE_CONSOLE;
+	driver->init_termios	= tty_std_termios;
+	driver->ve		= ve;
+	tty_set_operations(driver, &vt_tty_fops);
+
+	ret = tty_register_driver(driver);
+	if (ret) {
+		pr_err("Can't register vt master driver\n");
+		put_tty_driver(driver);
+		return ret;
+	}
+
+	for (i = 0; i < VZ_VT_MAX_DEVS; i++) {
+		dev_t dev = MKDEV(TTY_MAJOR, i);
+		struct device *d;
+
+		d = device_create(tty_class, NULL, dev, ve, "tty%i", i);
+		if (IS_ERR(d)) {
+			for (i--; i >= 0; i--)
+				device_destroy_namespace(tty_class, dev, ve);
+			tty_unregister_driver(driver);
+			put_tty_driver(driver);
+			return PTR_ERR(d);
+		}
+	}
+	ve->vz_vt_driver = driver;
+
+	return 0;
+#undef TTY_DRIVER_ALLOC_FLAGS
+}
+
+static void __vz_vt_ve_fini(struct ve_struct *ve)
+{
+	int i;
+
+	if (!ve->vz_vt_driver)
+		return;
+
+	for (i = 0; i < VZ_VT_MAX_DEVS; i++) {
+		dev_t dev = MKDEV(TTY_MAJOR, i);
+		device_destroy_namespace(tty_class, dev, ve);
+	}
+
+	tty_unregister_driver(ve->vz_vt_driver);
+	put_tty_driver(ve->vz_vt_driver);
+}
+
 static int __vz_con_ve_init(struct ve_struct *ve)
 {
 	struct device *d;
@@ -135,9 +243,14 @@ static int __vz_con_ve_init(struct ve_st
 
 int vz_con_ve_init(struct ve_struct *ve)
 {
-	if (ve != get_ve0())
-		return __vz_con_ve_init(ve);
-	return 0;
+	int ret = 0;
+
+	if (ve != get_ve0()) {
+		ret = __vz_con_ve_init(ve);
+		if (!ret)
+			ret = __vz_vt_ve_init(ve);
+	}
+	return ret;
 }
 EXPORT_SYMBOL_GPL(vz_con_ve_init);
 
@@ -145,6 +258,7 @@ static void __vz_con_ve_fini(struct ve_s
 {
 	dev_t dev = MKDEV(vz_cons_driver->major, vz_cons_driver->minor_start);
 	device_destroy_namespace(vz_con_class, dev, ve);
+	__vz_vt_ve_fini(ve);
 }
 
 void vz_con_ve_fini(struct ve_struct *ve)
@@ -260,3 +374,12 @@ struct tty_driver *vz_console_device(int
 	return vz_conm_driver;
 }
 EXPORT_SYMBOL_GPL(vz_console_device);
+
+struct tty_driver *vz_vt_device(struct ve_struct *ve, dev_t dev, int *index)
+{
+	BUG_ON(MINOR(dev) > VZ_VT_MAX_DEVS);
+
+	*index = MINOR(dev) ? MINOR(dev) - 1 : 0;
+	return ve->vz_vt_driver;
+}
+EXPORT_SYMBOL_GPL(vz_vt_device);



More information about the Devel mailing list