Commit 168942c9 authored by Peter Hurley's avatar Peter Hurley Committed by Greg Kroah-Hartman

tty: Refactor wait for ldisc refs out of tty_ldisc_hangup()

Refactor tty_ldisc_hangup() to extract standalone function,
tty_ldisc_hangup_wait_idle(), to wait for ldisc references
to be released.
Signed-off-by: default avatarPeter Hurley <peter@hurleysoftware.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 79901317
...@@ -550,6 +550,41 @@ static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout) ...@@ -550,6 +550,41 @@ static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout)
return ret > 0 ? 0 : -EBUSY; return ret > 0 ? 0 : -EBUSY;
} }
/**
* tty_ldisc_hangup_wait_idle - wait for the ldisc to become idle
* @tty: tty to wait for
*
* Wait for the line discipline to become idle. The discipline must
* have been halted for this to guarantee it remains idle.
*
* Caller must hold legacy and ->ldisc_mutex.
*/
static bool tty_ldisc_hangup_wait_idle(struct tty_struct *tty)
{
while (tty->ldisc) { /* Not yet closed */
if (atomic_read(&tty->ldisc->users) != 1) {
char cur_n[TASK_COMM_LEN], tty_n[64];
long timeout = 3 * HZ;
tty_unlock(tty);
while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
timeout = MAX_SCHEDULE_TIMEOUT;
printk_ratelimited(KERN_WARNING
"%s: waiting (%s) for %s took too long, but we keep waiting...\n",
__func__, get_task_comm(cur_n, current),
tty_name(tty, tty_n));
}
/* must reacquire both locks and preserve lock order */
mutex_unlock(&tty->ldisc_mutex);
tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
continue;
}
break;
}
return !!tty->ldisc;
}
/** /**
* tty_set_ldisc - set line discipline * tty_set_ldisc - set line discipline
* @tty: the terminal to set * @tty: the terminal to set
...@@ -826,7 +861,6 @@ void tty_ldisc_hangup(struct tty_struct *tty) ...@@ -826,7 +861,6 @@ void tty_ldisc_hangup(struct tty_struct *tty)
cancel_work_sync(&tty->port->buf.work); cancel_work_sync(&tty->port->buf.work);
set_bit(TTY_LDISC_HALTED, &tty->flags); set_bit(TTY_LDISC_HALTED, &tty->flags);
mutex_unlock(&tty->ldisc_mutex); mutex_unlock(&tty->ldisc_mutex);
retry:
tty_lock(tty); tty_lock(tty);
mutex_lock(&tty->ldisc_mutex); mutex_lock(&tty->ldisc_mutex);
...@@ -834,23 +868,7 @@ void tty_ldisc_hangup(struct tty_struct *tty) ...@@ -834,23 +868,7 @@ void tty_ldisc_hangup(struct tty_struct *tty)
reopen it. We could defer this to the next open but reopen it. We could defer this to the next open but
it means auditing a lot of other paths so this is it means auditing a lot of other paths so this is
a FIXME */ a FIXME */
if (tty->ldisc) { /* Not yet closed */ if (tty_ldisc_hangup_wait_idle(tty)) {
if (atomic_read(&tty->ldisc->users) != 1) {
char cur_n[TASK_COMM_LEN], tty_n[64];
long timeout = 3 * HZ;
tty_unlock(tty);
while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
timeout = MAX_SCHEDULE_TIMEOUT;
printk_ratelimited(KERN_WARNING
"%s: waiting (%s) for %s took too long, but we keep waiting...\n",
__func__, get_task_comm(cur_n, current),
tty_name(tty, tty_n));
}
mutex_unlock(&tty->ldisc_mutex);
goto retry;
}
if (reset == 0) { if (reset == 0) {
if (!tty_ldisc_reinit(tty, tty->termios.c_line)) if (!tty_ldisc_reinit(tty, tty->termios.c_line))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment