Commit 5f412b24 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] Fix locking for tty drivers when doing urgent characters

If you send a priority character (as is done for flow control) then the tty
driver can either have its own method for "jumping the queue" or the characrer
can be queued normally.  In the latter case we call the write method but
without the atomic_write_lock taken elsewhere.

Make this consistent.  Note that the send_xchar method if implemented remains
outside of the lock as it can jump ahead of a current write so must not be
locked out by it.
Signed-off-by: default avatarAlan Cox <alan@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 67cc0161
...@@ -423,24 +423,28 @@ static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars) ...@@ -423,24 +423,28 @@ static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
* *
* Send a high priority character to the tty even if stopped * Send a high priority character to the tty even if stopped
* *
* Locking: none * Locking: none for xchar method, write ordering for write method.
*
* FIXME: overlapping calls with start/stop tty lose state of tty
*/ */
static void send_prio_char(struct tty_struct *tty, char ch) static int send_prio_char(struct tty_struct *tty, char ch)
{ {
int was_stopped = tty->stopped; int was_stopped = tty->stopped;
if (tty->driver->send_xchar) { if (tty->driver->send_xchar) {
tty->driver->send_xchar(tty, ch); tty->driver->send_xchar(tty, ch);
return; return 0;
} }
if (mutex_lock_interruptible(&tty->atomic_write_lock))
return -ERESTARTSYS;
if (was_stopped) if (was_stopped)
start_tty(tty); start_tty(tty);
tty->driver->write(tty, &ch, 1); tty->driver->write(tty, &ch, 1);
if (was_stopped) if (was_stopped)
stop_tty(tty); stop_tty(tty);
mutex_unlock(&tty->atomic_write_lock);
return 0;
} }
int n_tty_ioctl(struct tty_struct * tty, struct file * file, int n_tty_ioctl(struct tty_struct * tty, struct file * file,
...@@ -514,11 +518,11 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, ...@@ -514,11 +518,11 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
break; break;
case TCIOFF: case TCIOFF:
if (STOP_CHAR(tty) != __DISABLED_CHAR) if (STOP_CHAR(tty) != __DISABLED_CHAR)
send_prio_char(tty, STOP_CHAR(tty)); return send_prio_char(tty, STOP_CHAR(tty));
break; break;
case TCION: case TCION:
if (START_CHAR(tty) != __DISABLED_CHAR) if (START_CHAR(tty) != __DISABLED_CHAR)
send_prio_char(tty, START_CHAR(tty)); return send_prio_char(tty, START_CHAR(tty));
break; break;
default: default:
return -EINVAL; return -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment