aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/pty.c
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/pty.c
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/pty.c')
-rw-r--r--drivers/char/pty.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index da2cb8c70c11..5acd29e6e043 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -110,7 +110,7 @@ static int pty_write(struct tty_struct *tty, const unsigned char *buf,
110 c = to->receive_room; 110 c = to->receive_room;
111 if (c > count) 111 if (c > count)
112 c = count; 112 c = count;
113 to->ldisc.ops->receive_buf(to, buf, NULL, c); 113 to->ldisc->ops->receive_buf(to, buf, NULL, c);
114 114
115 return c; 115 return c;
116} 116}
@@ -148,11 +148,11 @@ static int pty_chars_in_buffer(struct tty_struct *tty)
148 int count; 148 int count;
149 149
150 /* We should get the line discipline lock for "tty->link" */ 150 /* We should get the line discipline lock for "tty->link" */
151 if (!to || !to->ldisc.ops->chars_in_buffer) 151 if (!to || !to->ldisc->ops->chars_in_buffer)
152 return 0; 152 return 0;
153 153
154 /* The ldisc must report 0 if no characters available to be read */ 154 /* The ldisc must report 0 if no characters available to be read */
155 count = to->ldisc.ops->chars_in_buffer(to); 155 count = to->ldisc->ops->chars_in_buffer(to);
156 156
157 if (tty->driver->subtype == PTY_TYPE_SLAVE) 157 if (tty->driver->subtype == PTY_TYPE_SLAVE)
158 return count; 158 return count;
@@ -186,8 +186,8 @@ static void pty_flush_buffer(struct tty_struct *tty)
186 if (!to) 186 if (!to)
187 return; 187 return;
188 188
189 if (to->ldisc.ops->flush_buffer) 189 if (to->ldisc->ops->flush_buffer)
190 to->ldisc.ops->flush_buffer(to); 190 to->ldisc->ops->flush_buffer(to);
191 191
192 if (to->packet) { 192 if (to->packet) {
193 spin_lock_irqsave(&tty->ctrl_lock, flags); 193 spin_lock_irqsave(&tty->ctrl_lock, flags);