summaryrefslogtreecommitdiffstats
path: root/drivers/tty/tty_io.c
diff options
context:
space:
mode:
authorPeter Hurley <peter@hurleysoftware.com>2014-11-05 18:13:01 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-11-06 03:50:42 +0100
commit2aff5e2bc62db43e05c814461a08aff0fc2b7fe5 (patch)
tree8c43d997c471b171f8929fee681c1650c0f06c57 /drivers/tty/tty_io.c
parenttty: Simplify tty_release() state checks (diff)
downloadlinux-2aff5e2bc62db43e05c814461a08aff0fc2b7fe5.tar.xz
linux-2aff5e2bc62db43e05c814461a08aff0fc2b7fe5.zip
tty: Change tty lock order to master->slave
When releasing the master pty, the slave pty also needs to be locked to prevent concurrent tty count changes for the slave pty and to ensure that only one parallel master and slave release observe the final close, and proceed to destruct the pty pair. Conversely, when releasing the slave pty, locking the master pty is not necessary (since the master's state can be inferred by the slave tty count). Introduce tty_lock_slave()/tty_unlock_slave() which acquires/releases the tty lock of the slave pty. Remove tty_lock_pair()/tty_unlock_pair(). Dropping the tty_lock is no longer required to re-establish a stable lock order. Reviewed-by: Alan Cox <alan@linux.intel.com> 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.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index bd7cde3c56ef..4ecee2856ece 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -1790,7 +1790,9 @@ int tty_release(struct inode *inode, struct file *filp)
if (tty->ops->close)
tty->ops->close(tty, filp);
- tty_unlock(tty);
+ /* If tty is pty master, lock the slave pty (stable lock order) */
+ tty_lock_slave(o_tty);
+
/*
* Sanity check: if tty->count is going to zero, there shouldn't be
* any waiters on tty->read_wait or tty->write_wait. We test the
@@ -1804,8 +1806,6 @@ int tty_release(struct inode *inode, struct file *filp)
* Thus this test wouldn't be triggered at the time the slave closed,
* so we do it now.
*/
- tty_lock_pair(tty, o_tty);
-
while (1) {
do_sleep = 0;
@@ -1879,7 +1879,9 @@ int tty_release(struct inode *inode, struct file *filp)
/* check whether both sides are closing ... */
final = !tty->count && !(o_tty && o_tty->count);
- tty_unlock_pair(tty, o_tty);
+ tty_unlock_slave(o_tty);
+ tty_unlock(tty);
+
/* At this point, the tty->count == 0 should ensure a dead tty
cannot be re-opened by a racing opener */