aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-09-18 10:05:58 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-18 10:05:58 -0400
commit202c4675c55ddf6b443c7e057d2dff6b42ef71aa (patch)
treeb0340f27f46715cd40f882c123b83685daea99dd /drivers/char
parentdf58bee21ed218cb7dfb561a590b1bd2a99531cf (diff)
pty_write: don't do a tty_wakeup() when the buffers are full
Commit ac89a9174 ("pty: don't limit the writes to 'pty_space()' inside 'pty_write()'") removed the pty_space() checking, in order to let the regular tty buffer code limit the buffering itself. That was all good, but as a subtle side effect it meant that we'd be doing a tty_wakeup() even in the case where the buffers were all filled up, and didn't actually make any progress on the write. Which sounds innocuous, but it interacts very badly with the ppp_async code, which has an infinite loop in ppp_async_push() that tries to push out data to the tty. When we call tty_wakeup(), that loop ends up thinking that progress was made (see the subtle interactions between XMIT_WAKEUP and 'tty_stuffed' for details). End result: one unhappy ppp user. Fixed by noticing when tty_insert_flip_string() didn't actually do anything, and then not doing any more processing (including, very much not calling tty_wakeup()). Bisected-and-tested-by: Peter Volkov <pva@gentoo.org> Cc: stable@kernel.org (2.6.31) Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/pty.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index b33d6688e910..53761cefa915 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -120,8 +120,10 @@ static int pty_write(struct tty_struct *tty, const unsigned char *buf, int c)
120 /* Stuff the data into the input queue of the other end */ 120 /* Stuff the data into the input queue of the other end */
121 c = tty_insert_flip_string(to, buf, c); 121 c = tty_insert_flip_string(to, buf, c);
122 /* And shovel */ 122 /* And shovel */
123 tty_flip_buffer_push(to); 123 if (c) {
124 tty_wakeup(tty); 124 tty_flip_buffer_push(to);
125 tty_wakeup(tty);
126 }
125 } 127 }
126 return c; 128 return c;
127} 129}