From: Alan Cox <alan@redhat.com>
To: linux-kernel@vger.kernel.org
Subject: [PATCH 47/76] tty: shutdown method
Date: Sun, 05 Oct 2008 17:18:11 +0100 [thread overview]
Message-ID: <20081005161805.1997.35082.stgit@localhost.localdomain> (raw)
In-Reply-To: <20081005160231.1997.10462.stgit@localhost.localdomain>
Right now there are various drivers that try to use tty->count to know when
they get the final close. Aristeau Rozanski showed while debugging the vt
sysfs race that this isn't entirely safe.
Instead of driver side tricks to work around this introduce a shutdown which
is called when the tty is being destructed. This also means that the shutdown
method is tied into the refcounting.
Use this to rework the console close/sysfs logic.
Remove lots of special case code from the tty core code. The pty code can now
have a shutdown() method that replaces the special case hackery in the tree
free up paths.
Signed-off-by: Alan Cox <alan@redhat.com>
---
drivers/char/pty.c | 15 ++++++++++---
drivers/char/tty_io.c | 49 ++++++++++++++++++++++++++------------------
drivers/char/vt.c | 34 +++++++++++++++----------------
include/linux/tty.h | 3 ++-
include/linux/tty_driver.h | 6 +++++
5 files changed, 65 insertions(+), 42 deletions(-)
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 76b2793..ec09c1c 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -388,7 +388,14 @@ static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file,
return -ENOIOCTLCMD;
}
-static const struct tty_operations pty_unix98_ops = {
+static void pty_shutdown(struct tty_struct *tty)
+{
+ /* We have our own method as we don't use the tty index */
+ kfree(tty->termios);
+ kfree(tty->termios_locked);
+}
+
+static const struct tty_operations ptm_unix98_ops = {
.open = pty_open,
.close = pty_close,
.write = pty_write,
@@ -397,10 +404,10 @@ static const struct tty_operations pty_unix98_ops = {
.chars_in_buffer = pty_chars_in_buffer,
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
- .ioctl = pty_unix98_ioctl
+ .ioctl = pty_unix98_ioctl,
+ .shutdown = pty_shutdown
};
-
static void __init unix98_pty_init(void)
{
ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
@@ -427,7 +434,7 @@ static void __init unix98_pty_init(void)
ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
ptm_driver->other = pts_driver;
- tty_set_operations(ptm_driver, &pty_unix98_ops);
+ tty_set_operations(ptm_driver, &ptm_unix98_ops);
pts_driver->owner = THIS_MODULE;
pts_driver->driver_name = "pty_slave";
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 2e96ce0..f91704d 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1482,6 +1482,31 @@ release_mem_out:
goto end_init;
}
+void tty_free_termios(struct tty_struct *tty)
+{
+ struct ktermios *tp;
+ int idx = tty->index;
+ /* 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;
+ tty->driver->termios[idx] = NULL;
+ kfree(tp);
+
+ tp = tty->termios_locked;
+ tty->driver->termios_locked[idx] = NULL;
+ kfree(tp);
+ }
+}
+EXPORT_SYMBOL(tty_free_termios);
+
+void tty_shutdown(struct tty_struct *tty)
+{
+ tty->driver->ttys[tty->index] = NULL;
+ tty_free_termios(tty);
+}
+EXPORT_SYMBOL(tty_shutdown);
+
/**
* release_one_tty - release tty structure memory
* @kref: kref of tty we are obliterating
@@ -1499,27 +1524,11 @@ static void release_one_tty(struct kref *kref)
{
struct tty_struct *tty = container_of(kref, struct tty_struct, kref);
struct tty_driver *driver = tty->driver;
- int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM;
- struct ktermios *tp;
- int idx = tty->index;
-
- if (!devpts)
- tty->driver->ttys[idx] = NULL;
-
- 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);
- }
-
+ if (tty->ops->shutdown)
+ tty->ops->shutdown(tty);
+ else
+ tty_shutdown(tty);
tty->magic = 0;
/* FIXME: locking on tty->driver->refcount */
tty->driver->refcount--;
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index ec94521..37a45db 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -2758,6 +2758,12 @@ static int con_open(struct tty_struct *tty, struct file *filp)
ret = vc_allocate(currcons);
if (ret == 0) {
struct vc_data *vc = vc_cons[currcons].d;
+
+ /* Still being freed */
+ if (vc->vc_tty) {
+ release_console_sem();
+ return -ERESTARTSYS;
+ }
tty->driver_data = vc;
vc->vc_tty = tty;
@@ -2787,25 +2793,18 @@ static int con_open(struct tty_struct *tty, struct file *filp)
*/
static void con_close(struct tty_struct *tty, struct file *filp)
{
- mutex_lock(&tty_mutex);
- acquire_console_sem();
- if (tty && tty->count == 1) {
- struct vc_data *vc = tty->driver_data;
+ /* Nothing to do - we defer to shutdown */
+}
- if (vc)
- vc->vc_tty = NULL;
- tty->driver_data = NULL;
- vcs_remove_sysfs(tty);
- release_console_sem();
- mutex_unlock(&tty_mutex);
- /*
- * tty_mutex is released, but we still hold BKL, so there is
- * still exclusion against init_dev()
- */
- return;
- }
+static void con_shutdown(struct tty_struct *tty)
+{
+ struct vc_data *vc = tty->driver_data;
+ BUG_ON(vc == NULL);
+ acquire_console_sem();
+ vc->vc_tty = NULL;
+ vcs_remove_sysfs(tty);
release_console_sem();
- mutex_unlock(&tty_mutex);
+ tty_shutdown(tty);
}
static int default_italic_color = 2; // green (ASCII)
@@ -2930,6 +2929,7 @@ static const struct tty_operations con_ops = {
.throttle = con_throttle,
.unthrottle = con_unthrottle,
.resize = vt_resize,
+ .shutdown = con_shutdown
};
int __init vty_init(void)
diff --git a/include/linux/tty.h b/include/linux/tty.h
index e00393a..6e39c70 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -354,7 +354,8 @@ extern void tty_throttle(struct tty_struct *tty);
extern void tty_unthrottle(struct tty_struct *tty);
extern int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,
struct winsize *ws);
-
+extern void tty_shutdown(struct tty_struct *tty);
+extern void tty_free_termios(struct tty_struct *tty);
extern int is_current_pgrp_orphaned(void);
extern struct pid *tty_get_pgrp(struct tty_struct *tty);
extern int is_ignored(int sig);
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index ac6e58e..2322313 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -21,6 +21,11 @@
*
* Required method.
*
+ * void (*shutdown)(struct tty_struct * tty);
+ *
+ * This routine is called when a particular tty device is closed for
+ * the last time freeing up the resources.
+ *
* int (*write)(struct tty_struct * tty,
* const unsigned char *buf, int count);
*
@@ -200,6 +205,7 @@ struct tty_driver;
struct tty_operations {
int (*open)(struct tty_struct * tty, struct file * filp);
void (*close)(struct tty_struct * tty, struct file * filp);
+ void (*shutdown)(struct tty_struct *tty);
int (*write)(struct tty_struct * tty,
const unsigned char *buf, int count);
int (*put_char)(struct tty_struct *tty, unsigned char ch);
next prev parent reply other threads:[~2008-10-05 16:22 UTC|newest]
Thread overview: 88+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-10-05 16:04 [PATCH 00/76] Queued TTY Patches Alan Cox
2008-10-05 16:04 ` [PATCH 01/76] drivers/serial/crisv10.c: add missing put_tty_driver Alan Cox
2008-10-05 16:04 ` [PATCH 02/76] drivers/char/hvc_console.c: adjust call to put_tty_driver Alan Cox
2008-10-05 16:04 ` [PATCH 03/76] coldfire: scheduled SERIAL_COLDFIRE removal Alan Cox
2008-10-05 16:05 ` [PATCH 04/76] epca: call tty_port_init Alan Cox
2008-10-05 16:05 ` [PATCH 05/76] 8250: Remove NR_IRQ usage Alan Cox
2008-10-05 16:05 ` [PATCH 06/76] Blackfin Serial Driver: use __initdata for data, not __init Alan Cox
2008-10-05 16:05 ` [PATCH 07/76] Blackfin Serial Driver: Fix bug - should suspend/resume/remove all uart ports Alan Cox
2008-10-05 16:05 ` [PATCH 08/76] Blackfin Serial Driver: trim trailing whitespace -- no functional changes Alan Cox
2008-10-05 16:05 ` [PATCH 09/76] Blackfin Serial Driver: move common variables out of serial headers and into the serial driver Alan Cox
2008-10-05 16:05 ` [PATCH 10/76] Blackfin Serial Driver: Remove useless stop Alan Cox
2008-10-05 16:06 ` [PATCH 11/76] Blackfin Serial Driver: Fix bug - Don't call tx_stop in tx_transfer Alan Cox
2008-10-05 16:06 ` [PATCH 12/76] Blackfin Serial Driver: Fix bug - ircp fails on sir over Blackfin UART Alan Cox
2008-10-05 16:06 ` [PATCH 13/76] Blackfin Serial Driver: Fix bug - request UART2/3 peripheral mapped interrupts in PIO mode Alan Cox
2008-10-05 16:06 ` [PATCH 14/76] tty: move tioclinux from a special case Alan Cox
2008-10-05 16:06 ` [PATCH 15/76] uml: small cleanups and note bugs to be dealt with by uml authors Alan Cox
2008-10-05 16:06 ` [PATCH 16/76] Char: merge ip2main and ip2base Alan Cox
2008-10-05 16:06 ` [PATCH 17/76] ip2, cleanup globals Alan Cox
2008-10-05 16:07 ` [PATCH 18/76] ip2, fix sparse warnings Alan Cox
2008-10-05 16:07 ` [PATCH 19/76] ip2, init/deinit cleanup Alan Cox
2008-10-05 16:07 ` [PATCH 20/76] ip2: avoid add_timer with pending timer Alan Cox
2008-10-05 16:07 ` [PATCH 21/76] audit: Handle embedded NUL in TTY input auditing Alan Cox
2008-10-05 16:07 ` [PATCH 22/76] serial: Make uart_port's ioport "unsigned long" Alan Cox
2008-10-06 12:53 ` Josh Boyer
2008-10-05 16:07 ` [PATCH 23/76] tty: split the buffering from tty_io Alan Cox
2008-10-05 16:07 ` [PATCH 24/76] tty: Split tty_port into its own file Alan Cox
2008-10-05 16:08 ` [PATCH 25/76] pps: Reserve a line discipline number for PPS Alan Cox
2008-10-05 16:08 ` [PATCH 26/76] tty: Add a kref count Alan Cox
2008-10-06 10:20 ` Louis Rilling
2008-10-06 10:52 ` Alan Cox
2008-10-05 16:08 ` [PATCH 27/76] tty: use krefs to protect driver module counts Alan Cox
2008-10-05 16:08 ` [PATCH 28/76] Char: cyclades. remove bogus iomap Alan Cox
2008-10-05 16:08 ` [PATCH 29/76] Char: sx, fix io unmapping Alan Cox
2008-10-05 16:08 ` [PATCH 30/76] 8250: remove a few inlines of dubious value Alan Cox
2008-10-05 16:09 ` [PATCH 31/76] tty: Cris has a nice RS485 ioctl so we should steal it Alan Cox
2008-10-05 16:09 ` [PATCH 32/76] tty: ipw need reworking Alan Cox
2008-10-05 16:09 ` [PATCH 33/76] tty: Add termiox Alan Cox
2008-10-05 16:10 ` [PATCH 34/76] tty: Termios locking - sort out real_tty confusions and lock reads Alan Cox
2008-10-05 16:10 ` [PATCH 35/76] tty: compare the tty winsize Alan Cox
2008-10-05 16:10 ` [PATCH 36/76] tty: Make get_current_tty use a kref Alan Cox
2008-10-06 10:35 ` Louis Rilling
2008-10-06 10:56 ` Alan Cox
2008-10-05 16:10 ` [PATCH 37/76] tty: Move tty_write_message out of kernel/printk Alan Cox
2008-10-05 16:11 ` [PATCH 38/76] tty: usb-serial krefs Alan Cox
2008-10-06 5:36 ` Greg KH
2008-10-06 9:02 ` Alan Cox
2008-10-07 4:13 ` Greg KH
2008-10-05 16:12 ` [PATCH 39/76] tty: kref usage for isicom and moxa Alan Cox
2008-10-05 16:13 ` [PATCH 40/76] stallion: Use krefs Alan Cox
2008-10-05 16:14 ` [PATCH 41/76] mxser: Switch to kref tty Alan Cox
2008-10-05 16:15 ` [PATCH 42/76] tty: the vhangup syscall is racy Alan Cox
2008-10-05 16:15 ` [PATCH 43/76] tty: Redo current tty locking Alan Cox
2008-10-09 13:21 ` Derek Fawcus
2008-10-05 16:16 ` [PATCH 44/76] tty: Fix abusers of current->sighand->tty Alan Cox
2008-10-05 16:17 ` [PATCH 45/76] pty: If the administrator creates a device for a ptmx slave we should not error Alan Cox
2008-10-05 16:18 ` [PATCH 46/76] vt: remove bogus lock dropping Alan Cox
2008-10-05 16:18 ` Alan Cox [this message]
2008-10-05 16:18 ` [PATCH 48/76] tty: Remove more special casing and out of place code Alan Cox
2008-10-05 16:19 ` [PATCH 49/76] tty: Move parts of tty_init_dev into new functions Alan Cox
2008-10-05 16:19 ` [PATCH 50/76] tty: Clean up the tty_init_dev changes further Alan Cox
2008-10-05 16:20 ` [PATCH 51/76] tty: kref the tty driver object Alan Cox
2008-10-05 16:20 ` [PATCH 52/76] tty: More driver operations Alan Cox
2008-10-05 16:20 ` [PATCH 53/76] tty: Finish fixing up the init_dev interface to use ERR_PTR Alan Cox
2008-10-05 16:21 ` [PATCH 54/76] tty: extract the pty init time special cases Alan Cox
2008-10-05 16:21 ` [PATCH 55/76] Move tty lookup/reopen to caller Alan Cox
2008-10-05 16:21 ` [PATCH 56/76] Add an instance parameter devpts interfaces Alan Cox
2008-10-05 16:21 ` [PATCH 57/76] Simplify devpts_get_tty() Alan Cox
2008-10-05 16:21 ` [PATCH 58/76] Simplify devpts_pty_new() Alan Cox
2008-10-05 16:21 ` [PATCH 59/76] Simplify devpts_pty_kill Alan Cox
2008-10-05 16:22 ` [PATCH 60/76] pty: Coding style and polish Alan Cox
2008-10-05 16:22 ` [PATCH 61/76] pty: Fix allocation failure double free Alan Cox
2008-10-05 16:22 ` [PATCH 62/76] pty: simplify unix98 allocation Alan Cox
2008-10-05 16:22 ` [PATCH 63/76] tty: simplify ktermios allocation Alan Cox
2008-10-05 16:22 ` [PATCH 64/76] tty: some ICANON magic is in the wrong places Alan Cox
2008-10-05 16:23 ` [PATCH 65/76] tty: Fallout from tty-move-canon-specials Alan Cox
2008-10-05 16:23 ` [PATCH 66/76] tty: fix up gigaset a bit Alan Cox
2008-10-05 16:23 ` [PATCH 67/76] tty: Remove lots of NULL checks Alan Cox
2008-10-06 8:58 ` Geert Uytterhoeven
2008-10-06 10:50 ` Alan Cox
2008-10-05 16:23 ` [PATCH 68/76] tty: Minor tidyups and document fixes for n_tty Alan Cox
2008-10-05 16:24 ` [PATCH 69/76] hso: net driver using tty without locking Alan Cox
2008-10-05 16:24 ` [PATCH 70/76] applicom: Fix an unchecked user ioctl range and an error return Alan Cox
2008-10-05 16:24 ` [PATCH 71/76] serial-make-uart_ports-ioport-unsigned-long-fix Alan Cox
2008-10-05 16:24 ` [PATCH 72/76] serial: allow 8250 to be used on sparc Alan Cox
2008-10-05 16:24 ` [PATCH 73/76] serial: fix device name reporting when minor space is shared between drivers Alan Cox
2008-10-05 16:25 ` [PATCH 74/76] tty: tty_io.c shadows sparse fix Alan Cox
2008-10-05 16:25 ` [PATCH 75/76] usb: fix pl2303 initialization Alan Cox
2008-10-05 16:25 ` [PATCH 76/76] ftdi: A few errors are err() that should be debug which causes much spewage Alan Cox
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20081005161805.1997.35082.stgit@localhost.localdomain \
--to=alan@redhat.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox