Commit 52bce7f8 authored by Peter Hurley's avatar Peter Hurley Committed by Greg Kroah-Hartman

pty, n_tty: Simplify input processing on final close

When releasing one end of a pty pair, that end may just have written
to the other, which the input processing worker, flush_to_ldisc(), is
still working on but has not completed the copy to the other end's
read buffer. So input may not appear to be available to a waiting
reader but yet TTY_OTHER_CLOSED is now observed. The n_tty line
discipline has worked around this by waiting for input processing
to complete and then re-checking if input is available before
exiting with -EIO.

Since the tty/ldisc lock reordering, the wait for input processing
to complete can now occur during final close before setting
TTY_OTHER_CLOSED. In this way, a waiting reader is guaranteed to
see input available (if any) before observing TTY_OTHER_CLOSED.
Reviewed-by: default avatarAlan Cox <alan@linux.intel.com>
Signed-off-by: default avatarPeter Hurley <peter@hurleysoftware.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 1bb95415
...@@ -2197,14 +2197,9 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, ...@@ -2197,14 +2197,9 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
if (!input_available_p(tty, 0)) { if (!input_available_p(tty, 0)) {
if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
up_read(&tty->termios_rwsem);
tty_flush_to_ldisc(tty);
down_read(&tty->termios_rwsem);
if (!input_available_p(tty, 0)) {
retval = -EIO; retval = -EIO;
break; break;
} }
} else {
if (tty_hung_up_p(file)) if (tty_hung_up_p(file))
break; break;
if (!timeout) if (!timeout)
...@@ -2225,7 +2220,6 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, ...@@ -2225,7 +2220,6 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
down_read(&tty->termios_rwsem); down_read(&tty->termios_rwsem);
continue; continue;
} }
}
__set_current_state(TASK_RUNNING); __set_current_state(TASK_RUNNING);
if (ldata->icanon && !L_EXTPROC(tty)) { if (ldata->icanon && !L_EXTPROC(tty)) {
......
...@@ -53,6 +53,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp) ...@@ -53,6 +53,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
/* Review - krefs on tty_link ?? */ /* Review - krefs on tty_link ?? */
if (!tty->link) if (!tty->link)
return; return;
tty_flush_to_ldisc(tty->link);
set_bit(TTY_OTHER_CLOSED, &tty->link->flags); set_bit(TTY_OTHER_CLOSED, &tty->link->flags);
wake_up_interruptible(&tty->link->read_wait); wake_up_interruptible(&tty->link->read_wait);
wake_up_interruptible(&tty->link->write_wait); wake_up_interruptible(&tty->link->write_wait);
......
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