Commit c5c34d48 authored by Paul Fulghum's avatar Paul Fulghum Committed by Linus Torvalds

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: default avatarAlan Cox <alan@redhat.com>
Cc: Antonino Ingargiola <tritemio@gmail.com>
Signed-off-by: default avatarPaul Fulghum <paulkf@microgate.com>
Cc: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent e3bf460f
...@@ -368,6 +368,29 @@ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b) ...@@ -368,6 +368,29 @@ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
} }
} }
/**
* tty_buffer_flush - flush full tty buffers
* @tty: tty to flush
*
* flush all the buffers containing receive data
*
* Locking: none
*/
static void tty_buffer_flush(struct tty_struct *tty)
{
struct tty_buffer *thead;
unsigned long flags;
spin_lock_irqsave(&tty->buf.lock, flags);
while((thead = tty->buf.head) != NULL) {
tty->buf.head = thead->next;
tty_buffer_free(tty, thead);
}
tty->buf.tail = NULL;
spin_unlock_irqrestore(&tty->buf.lock, flags);
}
/** /**
* tty_buffer_find - find a free tty buffer * tty_buffer_find - find a free tty buffer
* @tty: tty owning the buffer * @tty: tty owning the buffer
...@@ -1248,6 +1271,7 @@ void tty_ldisc_flush(struct tty_struct *tty) ...@@ -1248,6 +1271,7 @@ void tty_ldisc_flush(struct tty_struct *tty)
ld->flush_buffer(tty); ld->flush_buffer(tty);
tty_ldisc_deref(ld); tty_ldisc_deref(ld);
} }
tty_buffer_flush(tty);
} }
EXPORT_SYMBOL_GPL(tty_ldisc_flush); EXPORT_SYMBOL_GPL(tty_ldisc_flush);
...@@ -3350,6 +3374,15 @@ int tty_ioctl(struct inode * inode, struct file * file, ...@@ -3350,6 +3374,15 @@ int tty_ioctl(struct inode * inode, struct file * file,
case TIOCMBIC: case TIOCMBIC:
case TIOCMBIS: case TIOCMBIS:
return tty_tiocmset(tty, file, cmd, p); return tty_tiocmset(tty, file, cmd, p);
case TCFLSH:
switch (arg) {
case TCIFLUSH:
case TCIOFLUSH:
/* flush tty buffer and allow ldisc to process ioctl */
tty_buffer_flush(tty);
break;
}
break;
} }
if (tty->driver->ioctl) { if (tty->driver->ioctl) {
retval = (tty->driver->ioctl)(tty, file, cmd, arg); retval = (tty->driver->ioctl)(tty, file, cmd, arg);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment