summaryrefslogtreecommitdiffstats
path: root/drivers/char/vt.c
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2008-10-13 10:41:30 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-13 09:51:42 -0700
commitfeebed6515a113eeb33919e9557a8b9710ea627c (patch)
tree0461178ee0c5e16ea90023e4b6386cb5c57d3391 /drivers/char/vt.c
parentbf7a06bcce205705ea5c7675cbb8ea9239ea30a0 (diff)
downloadlinux-feebed6515a113eeb33919e9557a8b9710ea627c.tar.gz
linux-feebed6515a113eeb33919e9557a8b9710ea627c.tar.bz2
linux-feebed6515a113eeb33919e9557a8b9710ea627c.zip
tty: shutdown method
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> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/vt.c')
-rw-r--r--drivers/char/vt.c34
1 files changed, 17 insertions, 17 deletions
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index ec94521c3118..37a45db5bae0 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)