From 79c1faa4511e78380cd643dac88a775062a08bc0 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 10 Oct 2015 16:00:51 -0400 Subject: tty: Remove tty_wait_until_sent_from_close() tty_wait_until_sent_from_close() drops the tty lock while waiting for the tty driver to finish sending previously accepted data (ie., data remaining in its write buffer and transmit fifo). tty_wait_until_sent_from_close() was added by commit a57a7bf3fc7e ("TTY: define tty_wait_until_sent_from_close") to prevent the entire tty subsystem from being unable to open new ttys while waiting for one tty to close while output drained. However, since commit 0911261d4cb6 ("tty: Don't take tty_mutex for tty count changes"), holding a tty lock while closing does not prevent other ttys from being opened/closed/hung up, but only prevents lifetime event changes for the tty under lock. Holding the tty lock while waiting for output to drain does prevent parallel non-blocking opens (O_NONBLOCK) from advancing or returning while the tty lock is held. However, all parallel opens _already_ block even if the tty lock is dropped while closing and the parallel open advances. Blocking in open has been in mainline since at least 2.6.29 (see tty_port_block_til_ready(); note the test for O_NONBLOCK is _after_ the wait while ASYNC_CLOSING). IOW, before this patch a non-blocking open will sleep anyway for the _entire_ duration of a parallel hardware shutdown, and when it wakes, the error return will cause a release of its tty, and it will restart with a fresh attempt to open. Similarly with a blocking open that is already waiting; when it's woken, the hardware shutdown has already completed to ASYNC_INITIALIZED is not set, which forces a release and restart as well. So, holding the tty lock across the _entire_ close (which is what this patch does), even while waiting for output to drain, is equivalent to the current outcome wrt parallel opens. Cc: Alan Cox Cc: David Laight CC: Arnd Bergmann CC: Karsten Keil CC: linuxppc-dev@lists.ozlabs.org Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_port.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers/tty/tty_port.c') diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 40b31835f80b..d7d9f9cde964 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -463,10 +463,7 @@ static void tty_port_drain_delay(struct tty_port *port, struct tty_struct *tty) schedule_timeout_interruptible(timeout); } -/* Caller holds tty lock. - * NB: may drop and reacquire tty lock (in tty_wait_until_sent_from_close()) - * so tty and tty port may have changed state (but not hung up or reopened). - */ +/* Caller holds tty lock. */ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct file *filp) { @@ -502,7 +499,7 @@ int tty_port_close_start(struct tty_port *port, if (tty->flow_stopped) tty_driver_flush_buffer(tty); if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent_from_close(tty, port->closing_wait); + tty_wait_until_sent(tty, port->closing_wait); if (port->drain_delay) tty_port_drain_delay(port, tty); } @@ -543,10 +540,6 @@ EXPORT_SYMBOL(tty_port_close_end); * tty_port_close * * Caller holds tty lock - * - * NB: may drop and reacquire tty lock (in tty_port_close_start()-> - * tty_wait_until_sent_from_close()) so tty and tty_port may have changed - * state (but not hung up or reopened). */ void tty_port_close(struct tty_port *port, struct tty_struct *tty, struct file *filp) -- cgit v1.2.1