|
@@ -558,29 +558,29 @@ static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout)
|
|
|
* have been halted for this to guarantee it remains idle.
|
|
|
*
|
|
|
* Caller must hold legacy and ->ldisc_mutex.
|
|
|
+ *
|
|
|
+ * NB: tty_set_ldisc() is prevented from changing the ldisc concurrently
|
|
|
+ * with this function by checking the TTY_HUPPING flag.
|
|
|
*/
|
|
|
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;
|
|
|
+ char cur_n[TASK_COMM_LEN], tty_n[64];
|
|
|
+ long timeout = 3 * HZ;
|
|
|
+
|
|
|
+ if (tty->ldisc) { /* Not yet closed */
|
|
|
+ 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));
|
|
|
}
|
|
|
- break;
|
|
|
+ /* must reacquire both locks and preserve lock order */
|
|
|
+ mutex_unlock(&tty->ldisc_mutex);
|
|
|
+ tty_lock(tty);
|
|
|
+ mutex_lock(&tty->ldisc_mutex);
|
|
|
}
|
|
|
return !!tty->ldisc;
|
|
|
}
|