Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 2335

kernel-2.6.18-128.1.10.el5.src.rpm

From: Aristeu Rozanski <aris@redhat.com>
Date: Tue, 2 Sep 2008 15:36:59 -0400
Subject: [tty] add shutdown method
Message-id: 20080902193659.GD10700@redhat.com
O-Subject: [RHEL5.3 PATCH 2/3] tty: add shutdown() method v2
Bugzilla: 239604
RH-Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>

https://bugzilla.redhat.com/show_bug.cgi?id=239604

Most drivers check for tty->count from inside the close() method to determine
if it's the last close. This is not safe and can cause the driver to not
release the resources (two last close() calls at same time, for both,
tty->count is 2).

This patch adds shutdown() operation to tty_driver, to be called only when the
tty is being freed.

kabi: this patch adds shutdown() to tty_driver structure. Since this structure
should be allocated by calling alloc_tty_driver() and the code is checking for
a specific flag to use this new element, it is safe to do it, even failing the
kabi test.

Note: the flag is leaving space for another flag. I'll repost the DTR/DSR patch
that includes two new elements on tty_driver using the same method, killing that
ugly tty_register_..()
Thanks to Rik to point this.

Updated: using __GENKSYMS__

upstream: 413c68538dc90edb4b0dea1eddab793804120d93 (linux-next)

diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 81cdad9..f2e58b9 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -2101,6 +2101,37 @@ release_mem_out:
 	goto end_init;
 }
 
+void tty_free_termios(struct tty_struct *tty)
+{
+	struct termios *tp;
+	int idx = tty->index;
+	int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM;
+
+	/* Kill this flag and push into drivers for locking etc */
+	if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
+		/* FIXME: Locking on ->termios array */
+		tp = tty->termios;
+		if (!devpts)
+			tty->driver->termios[idx] = NULL;
+		kfree(tp);
+
+		tp = tty->termios_locked;
+		if (!devpts)
+			tty->driver->termios_locked[idx] = NULL;
+		kfree(tp);
+	}
+}
+EXPORT_SYMBOL(tty_free_termios);
+
+void tty_shutdown(struct tty_struct *tty)
+{
+	int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM;
+
+	if (!devpts)
+		tty->driver->ttys[tty->index] = NULL;
+	tty_free_termios(tty);
+}
+
 /**
  *	release_one_tty		-	release tty structure memory
  *
@@ -2118,21 +2149,12 @@ static void release_one_tty(struct tty_struct *tty, int idx)
 {
 	struct termios *tp;
 	int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM;
+	void (*shutdown)(struct tty_struct *);
 
-	if (!devpts)
-		tty->driver->ttys[idx] = NULL;
-	if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
-		tp = tty->termios;
-		if (!devpts)
-			tty->driver->termios[idx] = NULL;
-		kfree(tp);
-
-		tp = tty->termios_locked;
-		if (!devpts)
-			tty->driver->termios_locked[idx] = NULL;
-		kfree(tp);
-	}
-
+	if (tty->driver->flags & TTY_DRIVER_HAS_SHUTDOWN)
+		tty->driver->shutdown(tty);
+	else
+		tty_shutdown(tty);
 
 	tty->magic = 0;
 	tty->driver->refcount--;
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index 58c961c..2846f11 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -213,6 +213,9 @@ struct tty_driver {
 			unsigned int set, unsigned int clear);
 
 	struct list_head tty_drivers;
+#ifndef __GENKSYMS__
+	void (*shutdown)(struct tty_struct *tty);
+#endif
 };
 
 extern struct list_head tty_drivers;
@@ -221,6 +224,8 @@ struct tty_driver *alloc_tty_driver(int lines);
 void put_tty_driver(struct tty_driver *driver);
 void tty_set_operations(struct tty_driver *driver, struct tty_operations *op);
 
+void tty_shutdown(struct tty_struct *tty);
+
 /* tty driver magic number */
 #define TTY_DRIVER_MAGIC		0x5402
 
@@ -254,12 +259,15 @@ void tty_set_operations(struct tty_driver *driver, struct tty_operations *op);
  * TTY_DRIVER_DEVPTS_MEM -- don't use the standard arrays, instead
  *	use dynamic memory keyed through the devpts filesystem.  This
  *	is only applicable to the pty driver.
+ * TTY_DRIVER_HAS_SHUTDOWN - if the driver implements the shutdown()
+ *	function
  */
 #define TTY_DRIVER_INSTALLED		0x0001
 #define TTY_DRIVER_RESET_TERMIOS	0x0002
 #define TTY_DRIVER_REAL_RAW		0x0004
 #define TTY_DRIVER_DYNAMIC_DEV		0x0008
 #define TTY_DRIVER_DEVPTS_MEM		0x0010
+#define TTY_DRIVER_HAS_SHUTDOWN		0x0020
 
 /* tty driver types */
 #define TTY_DRIVER_TYPE_SYSTEM		0x0001