提交 8f6576ad 编写于 作者: A Alan Cox 提交者: Linus Torvalds

tty: fix ldisc lock inversion trace

This is caused by tty_release using tty_lock_pair to lock both sides of
the pty/tty pair, and then tty_ldisc_release dropping and relocking one
side only.  We can drop both fine, so drop both to avoid any lock
ordering concerns.

Rework the release path to fix the new locking model.
Signed-off-by: NAlan Cox <alan@linux.intel.com>
Acked-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
上级 d3ca8b64
...@@ -894,6 +894,23 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) ...@@ -894,6 +894,23 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
tty_ldisc_enable(tty); tty_ldisc_enable(tty);
return 0; return 0;
} }
static void tty_ldisc_kill(struct tty_struct *tty)
{
mutex_lock(&tty->ldisc_mutex);
/*
* Now kill off the ldisc
*/
tty_ldisc_close(tty, tty->ldisc);
tty_ldisc_put(tty->ldisc);
/* Force an oops if we mess this up */
tty->ldisc = NULL;
/* Ensure the next open requests the N_TTY ldisc */
tty_set_termios_ldisc(tty, N_TTY);
mutex_unlock(&tty->ldisc_mutex);
}
/** /**
* tty_ldisc_release - release line discipline * tty_ldisc_release - release line discipline
* @tty: tty being shut down * @tty: tty being shut down
...@@ -912,27 +929,19 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) ...@@ -912,27 +929,19 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
* race with the set_ldisc code path. * race with the set_ldisc code path.
*/ */
tty_unlock(tty); tty_unlock_pair(tty, o_tty);
tty_ldisc_halt(tty); tty_ldisc_halt(tty);
tty_ldisc_flush_works(tty); tty_ldisc_flush_works(tty);
tty_lock(tty); if (o_tty) {
tty_ldisc_halt(o_tty);
mutex_lock(&tty->ldisc_mutex); tty_ldisc_flush_works(o_tty);
/* }
* Now kill off the ldisc tty_lock_pair(tty, o_tty);
*/
tty_ldisc_close(tty, tty->ldisc);
tty_ldisc_put(tty->ldisc);
/* Force an oops if we mess this up */
tty->ldisc = NULL;
/* Ensure the next open requests the N_TTY ldisc */
tty_set_termios_ldisc(tty, N_TTY);
mutex_unlock(&tty->ldisc_mutex);
/* This will need doing differently if we need to lock */ tty_ldisc_kill(tty);
if (o_tty) if (o_tty)
tty_ldisc_release(o_tty, NULL); tty_ldisc_kill(o_tty);
/* And the memory resources remaining (buffers, termios) will be /* And the memory resources remaining (buffers, termios) will be
disposed of when the kref hits zero */ disposed of when the kref hits zero */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册