Prevent an O_NDELAY writer from blocking when a tty write is blocked by the tty atomic writer mutex
Without this a tty write could block if a previous blocking tty write was
in progress on the same tty and blocked by a line discipline or hardware
event. Originally found and reported by Dave Johnson.
Signed-off-by: Alan Cox <alan@redhat.com>
Acked-by: Dave Johnson <djohnson+linux-kernel@sw.starentnetworks.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index 337a87f..37f7d34 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -780,13 +780,14 @@
poll_wait(filp, &tty->write_wait, wait);
/* set bits for operations that won't block */
- if(n_hdlc->rx_buf_list.head)
+ if (n_hdlc->rx_buf_list.head)
mask |= POLLIN | POLLRDNORM; /* readable */
if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
mask |= POLLHUP;
- if(tty_hung_up_p(filp))
+ if (tty_hung_up_p(filp))
mask |= POLLHUP;
- if(n_hdlc->tx_free_buf_list.head)
+ if (!tty_is_writelocked(tty) &&
+ n_hdlc->tx_free_buf_list.head)
mask |= POLLOUT | POLLWRNORM; /* writable */
}
return mask;
@@ -861,7 +862,7 @@
spin_lock_irqsave(&list->spinlock,flags);
buf->link=NULL;
- if(list->tail)
+ if (list->tail)
list->tail->link = buf;
else
list->head = buf;