aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/ip2
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2009-06-11 07:50:12 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-11 11:51:01 -0400
commitc65c9bc3efa5589f691276bb9db689119a711222 (patch)
treeccb86ffb28ecafa77623fb2789faae8e4c1e2c4b /drivers/char/ip2
parente8b70e7d3e86319a8b2aaabde3866833d92cd80f (diff)
tty: rewrite the ldisc locking
There are several pretty much unfixable races in the old ldisc code, especially with respect to pty behaviour and also to hangup. It's easier to rewrite the code than simply try and patch it up. This patch - splits the ldisc from the tty (so we will be able to refcount it more cleanly later) - introduces a mutex lock for ldisc changing on an active device - fixes the complete mess that hangup caused - implements hopefully correct setldisc/close/hangup locking There are still some problems around pty pairs that have always been there but at least it is now possible to understand the code and fix further problems. This fixes the following known bugs - hang up can leak ldisc references - hang up may not call open/close on ldisc in a matched way - pty/tty pairs can deadlock during an ldisc change - reading the ldisc proc files can cause every ldisc to be loaded and probably a few other of the mysterious ldisc race reports. I'm sure it also adds the odd new one. Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/ip2')
-rw-r--r--drivers/char/ip2/i2lib.c4
-rw-r--r--drivers/char/ip2/ip2main.c4
2 files changed, 4 insertions, 4 deletions
diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c
index 0061e18aff60..0d10b89218ed 100644
--- a/drivers/char/ip2/i2lib.c
+++ b/drivers/char/ip2/i2lib.c
@@ -868,11 +868,11 @@ i2Input(i2ChanStrPtr pCh)
868 amountToMove = count; 868 amountToMove = count;
869 } 869 }
870 // Move the first block 870 // Move the first block
871 pCh->pTTY->ldisc.ops->receive_buf( pCh->pTTY, 871 pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY,
872 &(pCh->Ibuf[stripIndex]), NULL, amountToMove ); 872 &(pCh->Ibuf[stripIndex]), NULL, amountToMove );
873 // If we needed to wrap, do the second data move 873 // If we needed to wrap, do the second data move
874 if (count > amountToMove) { 874 if (count > amountToMove) {
875 pCh->pTTY->ldisc.ops->receive_buf( pCh->pTTY, 875 pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY,
876 pCh->Ibuf, NULL, count - amountToMove ); 876 pCh->Ibuf, NULL, count - amountToMove );
877 } 877 }
878 // Bump and wrap the stripIndex all at once by the amount of data read. This 878 // Bump and wrap the stripIndex all at once by the amount of data read. This
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index afd9247cf082..517271c762e6 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -1315,8 +1315,8 @@ static inline void isig(int sig, struct tty_struct *tty, int flush)
1315 if (tty->pgrp) 1315 if (tty->pgrp)
1316 kill_pgrp(tty->pgrp, sig, 1); 1316 kill_pgrp(tty->pgrp, sig, 1);
1317 if (flush || !L_NOFLSH(tty)) { 1317 if (flush || !L_NOFLSH(tty)) {
1318 if ( tty->ldisc.ops->flush_buffer ) 1318 if ( tty->ldisc->ops->flush_buffer )
1319 tty->ldisc.ops->flush_buffer(tty); 1319 tty->ldisc->ops->flush_buffer(tty);
1320 i2InputFlush( tty->driver_data ); 1320 i2InputFlush( tty->driver_data );
1321 } 1321 }
1322} 1322}