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 /include/linux | |
| 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 'include/linux')
| -rw-r--r-- | include/linux/tty.h | 4 | ||||
| -rw-r--r-- | include/linux/tty_ldisc.h | 3 |
2 files changed, 2 insertions, 5 deletions
diff --git a/include/linux/tty.h b/include/linux/tty.h index 01ac30efd6a6..7269daf7632b 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
| @@ -238,7 +238,7 @@ struct tty_struct { | |||
| 238 | int index; | 238 | int index; |
| 239 | 239 | ||
| 240 | /* Protects ldisc changes: Lock tty not pty */ | 240 | /* Protects ldisc changes: Lock tty not pty */ |
| 241 | struct mutex ldisc_mutex; | 241 | struct ld_semaphore ldisc_sem; |
| 242 | struct tty_ldisc *ldisc; | 242 | struct tty_ldisc *ldisc; |
| 243 | 243 | ||
| 244 | struct mutex atomic_write_lock; | 244 | struct mutex atomic_write_lock; |
| @@ -305,8 +305,6 @@ struct tty_file_private { | |||
| 305 | #define TTY_DO_WRITE_WAKEUP 5 /* Call write_wakeup after queuing new */ | 305 | #define TTY_DO_WRITE_WAKEUP 5 /* Call write_wakeup after queuing new */ |
| 306 | #define TTY_PUSH 6 /* n_tty private */ | 306 | #define TTY_PUSH 6 /* n_tty private */ |
| 307 | #define TTY_CLOSING 7 /* ->close() in progress */ | 307 | #define TTY_CLOSING 7 /* ->close() in progress */ |
| 308 | #define TTY_LDISC 9 /* Line discipline attached */ | ||
| 309 | #define TTY_LDISC_CHANGING 10 /* Line discipline changing */ | ||
| 310 | #define TTY_LDISC_OPEN 11 /* Line discipline is open */ | 308 | #define TTY_LDISC_OPEN 11 /* Line discipline is open */ |
| 311 | #define TTY_PTY_LOCK 16 /* pty private */ | 309 | #define TTY_PTY_LOCK 16 /* pty private */ |
| 312 | #define TTY_NO_WRITE_SPLIT 17 /* Preserve write boundaries to driver */ | 310 | #define TTY_NO_WRITE_SPLIT 17 /* Preserve write boundaries to driver */ |
diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index a1b048999821..23bdd9debb84 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h | |||
| @@ -203,8 +203,7 @@ struct tty_ldisc_ops { | |||
| 203 | 203 | ||
| 204 | struct tty_ldisc { | 204 | struct tty_ldisc { |
| 205 | struct tty_ldisc_ops *ops; | 205 | struct tty_ldisc_ops *ops; |
| 206 | atomic_t users; | 206 | struct tty_struct *tty; |
| 207 | wait_queue_head_t wq_idle; | ||
| 208 | }; | 207 | }; |
| 209 | 208 | ||
| 210 | #define TTY_LDISC_MAGIC 0x5403 | 209 | #define TTY_LDISC_MAGIC 0x5403 |
