aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2012-05-29 08:45:16 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-29 13:42:13 -0400
commit8f6576ad476b2a22d05ddafd2ddaee102577a4ed (patch)
tree3c7e3b21dad828aa404ec5e6df5d8006cdb90815 /drivers/tty
parentd3ca8b64b97ef4dc54d7bb0b88bbc01a1fca8cb9 (diff)
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: Alan Cox <alan@linux.intel.com> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/tty_ldisc.c41
1 files changed, 25 insertions, 16 deletions
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index 173a9000a6cb..ba8be396a621 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -894,6 +894,23 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
894 tty_ldisc_enable(tty); 894 tty_ldisc_enable(tty);
895 return 0; 895 return 0;
896} 896}
897
898static void tty_ldisc_kill(struct tty_struct *tty)
899{
900 mutex_lock(&tty->ldisc_mutex);
901 /*
902 * Now kill off the ldisc
903 */
904 tty_ldisc_close(tty, tty->ldisc);
905 tty_ldisc_put(tty->ldisc);
906 /* Force an oops if we mess this up */
907 tty->ldisc = NULL;
908
909 /* Ensure the next open requests the N_TTY ldisc */
910 tty_set_termios_ldisc(tty, N_TTY);
911 mutex_unlock(&tty->ldisc_mutex);
912}
913
897/** 914/**
898 * tty_ldisc_release - release line discipline 915 * tty_ldisc_release - release line discipline
899 * @tty: tty being shut down 916 * @tty: tty being shut down
@@ -912,27 +929,19 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
912 * race with the set_ldisc code path. 929 * race with the set_ldisc code path.
913 */ 930 */
914 931
915 tty_unlock(tty); 932 tty_unlock_pair(tty, o_tty);
916 tty_ldisc_halt(tty); 933 tty_ldisc_halt(tty);
917 tty_ldisc_flush_works(tty); 934 tty_ldisc_flush_works(tty);
918 tty_lock(tty); 935 if (o_tty) {
919 936 tty_ldisc_halt(o_tty);
920 mutex_lock(&tty->ldisc_mutex); 937 tty_ldisc_flush_works(o_tty);
921 /* 938 }
922 * Now kill off the ldisc 939 tty_lock_pair(tty, o_tty);
923 */
924 tty_ldisc_close(tty, tty->ldisc);
925 tty_ldisc_put(tty->ldisc);
926 /* Force an oops if we mess this up */
927 tty->ldisc = NULL;
928 940
929 /* Ensure the next open requests the N_TTY ldisc */
930 tty_set_termios_ldisc(tty, N_TTY);
931 mutex_unlock(&tty->ldisc_mutex);
932 941
933 /* This will need doing differently if we need to lock */ 942 tty_ldisc_kill(tty);
934 if (o_tty) 943 if (o_tty)
935 tty_ldisc_release(o_tty, NULL); 944 tty_ldisc_kill(o_tty);
936 945
937 /* And the memory resources remaining (buffers, termios) will be 946 /* And the memory resources remaining (buffers, termios) will be
938 disposed of when the kref hits zero */ 947 disposed of when the kref hits zero */