tty: Simplify tty_set_ldisc() exit handling

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>
This commit is contained in:
Peter Hurley 2015-11-08 09:29:38 -05:00 committed by Greg Kroah-Hartman
parent 5841fc4b13
commit 63d8cb3f19

View File

@ -529,34 +529,21 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
tty_lock(tty); tty_lock(tty);
retval = tty_ldisc_lock(tty, 5 * HZ); retval = tty_ldisc_lock(tty, 5 * HZ);
if (retval) { if (retval)
tty_ldisc_put(new_ldisc); goto err;
tty_unlock(tty);
return retval;
}
/* /* Check the no-op case */
* Check the no-op case if (tty->ldisc->ops->num == ldisc)
*/ goto out;
if (tty->ldisc->ops->num == ldisc) { if (test_bit(TTY_HUPPED, &tty->flags)) {
tty_ldisc_unlock(tty); /* We were raced by hangup */
tty_ldisc_put(new_ldisc); retval = -EIO;
tty_unlock(tty); goto out;
return 0;
} }
old_ldisc = tty->ldisc; 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. */ /* Shutdown the old discipline. */
tty_ldisc_close(tty, old_ldisc); tty_ldisc_close(tty, old_ldisc);
@ -582,18 +569,15 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
the old ldisc (if it was restored as part of error cleanup the old ldisc (if it was restored as part of error cleanup
above). In either case, releasing a single reference from above). In either case, releasing a single reference from
the old ldisc is correct. */ the old ldisc is correct. */
new_ldisc = old_ldisc;
tty_ldisc_put(old_ldisc); out:
/*
* Allow ldisc referencing to occur again
*/
tty_ldisc_unlock(tty); tty_ldisc_unlock(tty);
/* Restart the work queue in case no characters kick it off. Safe if /* Restart the work queue in case no characters kick it off. Safe if
already running */ already running */
tty_buffer_restart_work(tty->port); tty_buffer_restart_work(tty->port);
err:
tty_ldisc_put(new_ldisc); /* drop the extra reference */
tty_unlock(tty); tty_unlock(tty);
return retval; return retval;
} }