2008-11-24 13:40:27

by Thomas Pfaff

[permalink] [raw]
Subject: [PATCH] tty: Fix async io write notifications

From: Thomas Pfaff <[email protected]>

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 <[email protected]>
Cc: Alan Cox <[email protected]>
---
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;
}


2008-11-24 14:22:00

by Alan

[permalink] [raw]
Subject: Re: [PATCH] tty: Fix async io write notifications

On Mon, 24 Nov 2008 14:40:15 +0100 (CET)
Thomas Pfaff <[email protected]> wrote:

> he 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 <[email protected]>

I had done a patch already but yours is somewhat nicer so I've merged
yours instead with some tweaks as it clashed with an existing N_TTY patch

I left the tty->fasync check in the if (in case the user clears async I/O
events) and I reversed the tests on the end of n_tty_write simply
because the compiler has the variables we need to check to hand but not
tty->fasync.

This all looks good to me. It breaks on ptys but that is another bug and
I'll merge a patch to fix the ptys next.

Alan