[Xenial,1/7] tty: Simplify tty_set_ldisc() exit handling

Submitted by Kamal Mostafa on Aug. 7, 2017, 10:52 p.m.

Details

Message ID 1502146366-26393-2-git-send-email-kamal@canonical.com
State New
Headers show

Commit Message

Kamal Mostafa Aug. 7, 2017, 10:52 p.m.
From: Peter Hurley <peter@hurleysoftware.com>

BugLink: http://bugs.launchpad.net/bugs/1709126

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@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit 63d8cb3f19dabb409a09b4f2b8827934ab9365a3)
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
---
 drivers/tty/tty_ldisc.c | 42 +++++++++++++-----------------------------
 1 file changed, 13 insertions(+), 29 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index 9bee25c..6f59f14 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -536,34 +536,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);
 
@@ -589,18 +576,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;
 }