diff options
author | Paul Fulghum <paulkf@microgate.com> | 2007-05-12 13:36:55 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-12 13:55:39 -0400 |
commit | c5c34d4862e18ef07c1276d233507f540fb5a532 (patch) | |
tree | a0645f236a8bd2492476d1e24fbf94d5cd7edc30 /drivers/char/tty_io.c | |
parent | e3bf460f3eb86cdbc76725a0dac1f191e796676c (diff) |
tty: flush flip buffer on ldisc input queue flush
Flush the tty flip buffer when the line discipline input queue is flushed,
including the user call tcflush(TCIFLUSH/TCIOFLUSH). This prevents
unexpected stale data after a user application calls tcflush().
Signed-off-by: Alan Cox <alan@redhat.com>
Cc: Antonino Ingargiola <tritemio@gmail.com>
Signed-off-by: Paul Fulghum <paulkf@microgate.com>
Cc: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/tty_io.c')
-rw-r--r-- | drivers/char/tty_io.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index bc849957508d..75d2a46e106f 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -369,6 +369,29 @@ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b) | |||
369 | } | 369 | } |
370 | 370 | ||
371 | /** | 371 | /** |
372 | * tty_buffer_flush - flush full tty buffers | ||
373 | * @tty: tty to flush | ||
374 | * | ||
375 | * flush all the buffers containing receive data | ||
376 | * | ||
377 | * Locking: none | ||
378 | */ | ||
379 | |||
380 | static void tty_buffer_flush(struct tty_struct *tty) | ||
381 | { | ||
382 | struct tty_buffer *thead; | ||
383 | unsigned long flags; | ||
384 | |||
385 | spin_lock_irqsave(&tty->buf.lock, flags); | ||
386 | while((thead = tty->buf.head) != NULL) { | ||
387 | tty->buf.head = thead->next; | ||
388 | tty_buffer_free(tty, thead); | ||
389 | } | ||
390 | tty->buf.tail = NULL; | ||
391 | spin_unlock_irqrestore(&tty->buf.lock, flags); | ||
392 | } | ||
393 | |||
394 | /** | ||
372 | * tty_buffer_find - find a free tty buffer | 395 | * tty_buffer_find - find a free tty buffer |
373 | * @tty: tty owning the buffer | 396 | * @tty: tty owning the buffer |
374 | * @size: characters wanted | 397 | * @size: characters wanted |
@@ -1248,6 +1271,7 @@ void tty_ldisc_flush(struct tty_struct *tty) | |||
1248 | ld->flush_buffer(tty); | 1271 | ld->flush_buffer(tty); |
1249 | tty_ldisc_deref(ld); | 1272 | tty_ldisc_deref(ld); |
1250 | } | 1273 | } |
1274 | tty_buffer_flush(tty); | ||
1251 | } | 1275 | } |
1252 | 1276 | ||
1253 | EXPORT_SYMBOL_GPL(tty_ldisc_flush); | 1277 | EXPORT_SYMBOL_GPL(tty_ldisc_flush); |
@@ -3350,6 +3374,15 @@ int tty_ioctl(struct inode * inode, struct file * file, | |||
3350 | case TIOCMBIC: | 3374 | case TIOCMBIC: |
3351 | case TIOCMBIS: | 3375 | case TIOCMBIS: |
3352 | return tty_tiocmset(tty, file, cmd, p); | 3376 | return tty_tiocmset(tty, file, cmd, p); |
3377 | case TCFLSH: | ||
3378 | switch (arg) { | ||
3379 | case TCIFLUSH: | ||
3380 | case TCIOFLUSH: | ||
3381 | /* flush tty buffer and allow ldisc to process ioctl */ | ||
3382 | tty_buffer_flush(tty); | ||
3383 | break; | ||
3384 | } | ||
3385 | break; | ||
3353 | } | 3386 | } |
3354 | if (tty->driver->ioctl) { | 3387 | if (tty->driver->ioctl) { |
3355 | retval = (tty->driver->ioctl)(tty, file, cmd, arg); | 3388 | retval = (tty->driver->ioctl)(tty, file, cmd, arg); |