diff options
author | Peter Hurley <peter@hurleysoftware.com> | 2013-06-15 07:04:48 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-07-23 19:38:34 -0400 |
commit | 36697529b5bbe36911e39a6309e7a7c9250d280a (patch) | |
tree | 5cbffa976994cb798e00d60eccb46c6cafc369a1 /drivers/tty/tty_io.c | |
parent | d2c438905f9f718b3d9f5d89ce163fc22bd33995 (diff) |
tty: Replace ldisc locking with ldisc_sem
Line discipline locking was performed with a combination of
a mutex, a status bit, a count, and a waitqueue -- basically,
a rw semaphore.
Replace the existing combination with an ld_semaphore.
Fixes:
1) the 'reference acquire after ldisc locked' bug
2) the over-complicated halt mechanism
3) lock order wrt. tty_lock()
4) dropping locks while changing ldisc
5) previously unidentified deadlock while locking ldisc from
both linked ttys concurrently
6) previously unidentified recursive deadlocks
Adds much-needed lockdep diagnostics.
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/tty_io.c')
-rw-r--r-- | drivers/tty/tty_io.c | 7 |
1 files changed, 3 insertions, 4 deletions
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index fa80af3656a3..0fa5db4c7a7a 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c | |||
@@ -1388,8 +1388,7 @@ static int tty_reopen(struct tty_struct *tty) | |||
1388 | struct tty_driver *driver = tty->driver; | 1388 | struct tty_driver *driver = tty->driver; |
1389 | 1389 | ||
1390 | if (test_bit(TTY_CLOSING, &tty->flags) || | 1390 | if (test_bit(TTY_CLOSING, &tty->flags) || |
1391 | test_bit(TTY_HUPPING, &tty->flags) || | 1391 | test_bit(TTY_HUPPING, &tty->flags)) |
1392 | test_bit(TTY_LDISC_CHANGING, &tty->flags)) | ||
1393 | return -EIO; | 1392 | return -EIO; |
1394 | 1393 | ||
1395 | if (driver->type == TTY_DRIVER_TYPE_PTY && | 1394 | if (driver->type == TTY_DRIVER_TYPE_PTY && |
@@ -1405,7 +1404,7 @@ static int tty_reopen(struct tty_struct *tty) | |||
1405 | } | 1404 | } |
1406 | tty->count++; | 1405 | tty->count++; |
1407 | 1406 | ||
1408 | WARN_ON(!test_bit(TTY_LDISC, &tty->flags)); | 1407 | WARN_ON(!tty->ldisc); |
1409 | 1408 | ||
1410 | return 0; | 1409 | return 0; |
1411 | } | 1410 | } |
@@ -3017,7 +3016,7 @@ void initialize_tty_struct(struct tty_struct *tty, | |||
3017 | tty->pgrp = NULL; | 3016 | tty->pgrp = NULL; |
3018 | mutex_init(&tty->legacy_mutex); | 3017 | mutex_init(&tty->legacy_mutex); |
3019 | mutex_init(&tty->termios_mutex); | 3018 | mutex_init(&tty->termios_mutex); |
3020 | mutex_init(&tty->ldisc_mutex); | 3019 | init_ldsem(&tty->ldisc_sem); |
3021 | init_waitqueue_head(&tty->write_wait); | 3020 | init_waitqueue_head(&tty->write_wait); |
3022 | init_waitqueue_head(&tty->read_wait); | 3021 | init_waitqueue_head(&tty->read_wait); |
3023 | INIT_WORK(&tty->hangup_work, do_tty_hangup); | 3022 | INIT_WORK(&tty->hangup_work, do_tty_hangup); |