Perform common exit for both successful and error exit handling
in tty_set_ldisc(). Fixes unlikely possibility of failing to restart
input kworker when switching to the same line discipline (noop case).

Signed-off-by: Peter Hurley <[email protected]>
---

Requires: "tty: Fix direct use of tty buffer work"

 drivers/tty/tty_ldisc.c | 42 +++++++++++++-----------------------------
 1 file changed, 13 insertions(+), 29 deletions(-)

diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index 2cf6826..b776f2e 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -527,34 +527,21 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 
        tty_lock(tty);
        retval = tty_ldisc_lock(tty, 5 * HZ);
-       if (retval) {
-               tty_ldisc_put(new_ldisc);
-               tty_unlock(tty);
-               return retval;
-       }
+       if (retval)
+               goto err;
 
-       /*
-        *      Check the no-op case
-        */
+       /* Check the no-op case */
+       if (tty->ldisc->ops->num == ldisc)
+               goto out;
 
-       if (tty->ldisc->ops->num == ldisc) {
-               tty_ldisc_unlock(tty);
-               tty_ldisc_put(new_ldisc);
-               tty_unlock(tty);
-               return 0;
+       if (test_bit(TTY_HUPPED, &tty->flags)) {
+               /* We were raced by hangup */
+               retval = -EIO;
+               goto out;
        }
 
        old_ldisc = tty->ldisc;
 
-       if (test_bit(TTY_HUPPED, &tty->flags)) {
-               /* We were raced by the hangup method. It will have stomped
-                  the ldisc data and closed the ldisc down */
-               tty_ldisc_unlock(tty);
-               tty_ldisc_put(new_ldisc);
-               tty_unlock(tty);
-               return -EIO;
-       }
-
        /* Shutdown the old discipline. */
        tty_ldisc_close(tty, old_ldisc);
 
@@ -580,18 +567,15 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
           the old ldisc (if it was restored as part of error cleanup
           above). In either case, releasing a single reference from
           the old ldisc is correct. */
-
-       tty_ldisc_put(old_ldisc);
-
-       /*
-        *      Allow ldisc referencing to occur again
-        */
+       new_ldisc = old_ldisc;
+out:
        tty_ldisc_unlock(tty);
 
        /* Restart the work queue in case no characters kick it off. Safe if
           already running */
        tty_buffer_restart_work(tty->port);
-
+err:
+       tty_ldisc_put(new_ldisc);       /* drop the extra reference */
        tty_unlock(tty);
        return retval;
 }
-- 
2.6.3

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

Reply via email to