[PATCH] tty: Simplify tty_set_ldisc() exit handling

From: Peter Hurley
Date: Sun Nov 08 2015 - 09:29:50 EST


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 <peter@xxxxxxxxxxxxxxxxxx>
---

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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/