Skip to content

Commit

Permalink
tty: Replace ldisc locking with ldisc_sem
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
peterhurley authored and gregkh committed Jul 23, 2013
1 parent d2c4389 commit 3669752
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 293 deletions.
2 changes: 1 addition & 1 deletion drivers/tty/tty_buffer.c
Expand Up @@ -429,7 +429,7 @@ static void flush_to_ldisc(struct work_struct *work)
return;

disc = tty_ldisc_ref(tty);
if (disc == NULL) /* !TTY_LDISC */
if (disc == NULL)
return;

spin_lock_irqsave(&buf->lock, flags);
Expand Down
7 changes: 3 additions & 4 deletions drivers/tty/tty_io.c
Expand Up @@ -1388,8 +1388,7 @@ static int tty_reopen(struct tty_struct *tty)
struct tty_driver *driver = tty->driver;

if (test_bit(TTY_CLOSING, &tty->flags) ||
test_bit(TTY_HUPPING, &tty->flags) ||
test_bit(TTY_LDISC_CHANGING, &tty->flags))
test_bit(TTY_HUPPING, &tty->flags))
return -EIO;

if (driver->type == TTY_DRIVER_TYPE_PTY &&
Expand All @@ -1405,7 +1404,7 @@ static int tty_reopen(struct tty_struct *tty)
}
tty->count++;

WARN_ON(!test_bit(TTY_LDISC, &tty->flags));
WARN_ON(!tty->ldisc);

return 0;
}
Expand Down Expand Up @@ -3017,7 +3016,7 @@ void initialize_tty_struct(struct tty_struct *tty,
tty->pgrp = NULL;
mutex_init(&tty->legacy_mutex);
mutex_init(&tty->termios_mutex);
mutex_init(&tty->ldisc_mutex);
init_ldsem(&tty->ldisc_sem);
init_waitqueue_head(&tty->write_wait);
init_waitqueue_head(&tty->read_wait);
INIT_WORK(&tty->hangup_work, do_tty_hangup);
Expand Down

0 comments on commit 3669752

Please sign in to comment.