summary refs log tree commit diff
path: root/drivers/char/n_hdlc.c
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2007-07-15 23:39:43 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-16 09:05:41 -0700
commit9c1729db3e6d738f872bcb090212af00473bf666 (patch)
treebe68b99784607953fb50d9330d34c2728215be57 /drivers/char/n_hdlc.c
parentc9c64155f5a81b4b41e98f9fb9c464a565c1bf72 (diff)
downloadlinux-9c1729db3e6d738f872bcb090212af00473bf666.tar.gz
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>
Diffstat (limited to 'drivers/char/n_hdlc.c')
-rw-r--r--drivers/char/n_hdlc.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index 337a87f86a3b..37f7d3403040 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -780,13 +780,14 @@ static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp,
 		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 @@ static void n_hdlc_buf_put(struct n_hdlc_buf_list *list,
 	spin_lock_irqsave(&list->spinlock,flags);
 	
 	buf->link=NULL;
-	if(list->tail)
+	if (list->tail)
 		list->tail->link = buf;
 	else
 		list->head = buf;