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:
parent
5841fc4b13
commit
63d8cb3f19
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user