[PATCH] tty: Fix async io write notifications

From: Thomas Pfaff
Date: Mon Nov 24 2008 - 08:40:27 EST


From: Thomas Pfaff <tpfaff@xxxxxxx>

The N_TTY ldisc layer does not send SIGIO POLL_OUTs correctly when output is
possible due to flawed handling of the TTY_DO_WRITE_WAKEUP bit. It will either
send no SIGIOs at all or on every tty wakeup.

The fix is to set the bit when the tty driver write would block and test and
clear it on write wakeup.

Signed-off-by: Thomas Pfaff <tpfaff@xxxxxxx>
Cc: Alan Cox <alan@xxxxxxxxxxxxxxxxxxx>
---
drivers/char/n_tty.c | 8 +++++---
1 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index efbfe96..4e0f4be 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -923,10 +923,8 @@ handle_newline:

static void n_tty_write_wakeup(struct tty_struct *tty)
{
- if (tty->fasync) {
- set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+ if (test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags))
kill_fasync(&tty->fasync, SIGIO, POLL_OUT);
- }
}

/**
@@ -1556,6 +1554,8 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
}
if (!nr)
break;
+ if (tty->fasync)
+ set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
if (file->f_flags & O_NONBLOCK) {
retval = -EAGAIN;
break;
@@ -1565,6 +1565,8 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
break_out:
__set_current_state(TASK_RUNNING);
remove_wait_queue(&tty->write_wait, &wait);
+ if (tty->fasync && (b - buf) != nr)
+ set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
return (b - buf) ? b - buf : retval;
}

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/