tty: Only guarantee termios read safety for throttle/unthrottle
authorPeter Hurley <peter@hurleysoftware.com>
Sat, 15 Jun 2013 13:14:31 +0000 (09:14 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 23 Jul 2013 23:43:02 +0000 (16:43 -0700)
No tty driver modifies termios during throttle() or unthrottle().
Therefore, only read safety is required.

However, tty_throttle_safe and tty_unthrottle_safe must still be
mutually exclusive; introduce throttle_mutex for that purpose.

Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/n_tty.c
drivers/tty/tty_io.c
drivers/tty/tty_ioctl.c
include/linux/tty.h

index d0c8805d813171a9f4ae1297fa67b7dbdabcbd90..b78ee464bd09ac431d5484ddaa1efca8c62aaeee 100644 (file)
@@ -1518,9 +1518,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp,
                tty_set_flow_change(tty, TTY_THROTTLE_SAFE);
                if (receive_room(tty) >= TTY_THRESHOLD_THROTTLE)
                        break;
-               up_read(&tty->termios_rwsem);
                throttled = tty_throttle_safe(tty);
-               down_read(&tty->termios_rwsem);
                if (!throttled)
                        break;
        }
@@ -2086,9 +2084,7 @@ do_it_again:
                        if (!tty->count)
                                break;
                        n_tty_set_room(tty);
-                       up_read(&tty->termios_rwsem);
                        unthrottled = tty_unthrottle_safe(tty);
-                       down_read(&tty->termios_rwsem);
                        if (!unthrottled)
                                break;
                }
index 639e24ade9bf349cb86830eae86ddd6cb94e2906..1b32da6f6cdd417ebe8fdac4ba1655281367901f 100644 (file)
@@ -3015,6 +3015,7 @@ void initialize_tty_struct(struct tty_struct *tty,
        tty->session = NULL;
        tty->pgrp = NULL;
        mutex_init(&tty->legacy_mutex);
+       mutex_init(&tty->throttle_mutex);
        init_rwsem(&tty->termios_rwsem);
        init_ldsem(&tty->ldisc_sem);
        init_waitqueue_head(&tty->write_wait);
index 9ce20df8a2c8d086a2bbb889d4a47d079008731e..03ba081c577251a0947466b79f23b36b359b51c1 100644 (file)
@@ -151,7 +151,7 @@ int tty_throttle_safe(struct tty_struct *tty)
 {
        int ret = 0;
 
-       down_write(&tty->termios_rwsem);
+       mutex_lock(&tty->throttle_mutex);
        if (!test_bit(TTY_THROTTLED, &tty->flags)) {
                if (tty->flow_change != TTY_THROTTLE_SAFE)
                        ret = 1;
@@ -161,7 +161,7 @@ int tty_throttle_safe(struct tty_struct *tty)
                                tty->ops->throttle(tty);
                }
        }
-       up_write(&tty->termios_rwsem);
+       mutex_unlock(&tty->throttle_mutex);
 
        return ret;
 }
@@ -182,7 +182,7 @@ int tty_unthrottle_safe(struct tty_struct *tty)
 {
        int ret = 0;
 
-       down_write(&tty->termios_rwsem);
+       mutex_lock(&tty->throttle_mutex);
        if (test_bit(TTY_THROTTLED, &tty->flags)) {
                if (tty->flow_change != TTY_UNTHROTTLE_SAFE)
                        ret = 1;
@@ -192,7 +192,7 @@ int tty_unthrottle_safe(struct tty_struct *tty)
                                tty->ops->unthrottle(tty);
                }
        }
-       up_write(&tty->termios_rwsem);
+       mutex_unlock(&tty->throttle_mutex);
 
        return ret;
 }
index d3042076d163860f93a8d162766917bfd1136731..57a70d1d0412a9dcb8f27602c6dd67d584561baa 100644 (file)
@@ -244,6 +244,7 @@ struct tty_struct {
 
        struct mutex atomic_write_lock;
        struct mutex legacy_mutex;
+       struct mutex throttle_mutex;
        struct rw_semaphore termios_rwsem;
        spinlock_t ctrl_lock;
        /* Termios values are protected by the termios rwsem */