aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2010-06-01 16:53:06 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-08-10 16:47:43 -0400
commit60af22d2ed490554cc92c8d0fed0b5b9cf687568 (patch)
tree6c9d1b2d9b5c409dc6a38f26ed5b7ec0f37a041a /drivers/char
parentbe1bc2889a4db4961ef69f47fb471ecae9f23ade (diff)
tty: reorder ldisc locking
We need to release the BTM in paste_selection() when sleeping in tty_ldisc_ref_wait to avoid deadlocks with tty_ldisc_enable. In tty_set_ldisc, we now always grab the BTM before taking the ldisc_mutex in order to avoid AB-BA deadlocks between the two. tty_ldisc_halt potentially blocks on a workqueue function that takes the BTM, so we must release the BTM before calling it. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/selection.c9
-rw-r--r--drivers/char/tty_ldisc.c24
2 files changed, 27 insertions, 6 deletions
diff --git a/drivers/char/selection.c b/drivers/char/selection.c
index 85211a3a5811..75889cd9375f 100644
--- a/drivers/char/selection.c
+++ b/drivers/char/selection.c
@@ -319,8 +319,13 @@ int paste_selection(struct tty_struct *tty)
319 poke_blanked_console(); 319 poke_blanked_console();
320 release_console_sem(); 320 release_console_sem();
321 321
322 ld = tty_ldisc_ref_wait(tty); 322 ld = tty_ldisc_ref(tty);
323 323 if (!ld) {
324 tty_unlock();
325 ld = tty_ldisc_ref_wait(tty);
326 tty_lock();
327 }
328
324 add_wait_queue(&vc->paste_wait, &wait); 329 add_wait_queue(&vc->paste_wait, &wait);
325 while (sel_buffer && sel_buffer_lth > pasted) { 330 while (sel_buffer && sel_buffer_lth > pasted) {
326 set_current_state(TASK_INTERRUPTIBLE); 331 set_current_state(TASK_INTERRUPTIBLE);
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c
index 97681ffd6cbd..0f494799da89 100644
--- a/drivers/char/tty_ldisc.c
+++ b/drivers/char/tty_ldisc.c
@@ -582,6 +582,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
582 582
583 tty_wait_until_sent(tty, 0); 583 tty_wait_until_sent(tty, 0);
584 584
585 tty_lock();
585 mutex_lock(&tty->ldisc_mutex); 586 mutex_lock(&tty->ldisc_mutex);
586 587
587 /* 588 /*
@@ -591,13 +592,13 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
591 592
592 while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { 593 while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) {
593 mutex_unlock(&tty->ldisc_mutex); 594 mutex_unlock(&tty->ldisc_mutex);
595 tty_unlock();
594 wait_event(tty_ldisc_wait, 596 wait_event(tty_ldisc_wait,
595 test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); 597 test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0);
598 tty_lock();
596 mutex_lock(&tty->ldisc_mutex); 599 mutex_lock(&tty->ldisc_mutex);
597 } 600 }
598 601
599 tty_lock();
600
601 set_bit(TTY_LDISC_CHANGING, &tty->flags); 602 set_bit(TTY_LDISC_CHANGING, &tty->flags);
602 603
603 /* 604 /*
@@ -634,8 +635,8 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
634 635
635 flush_scheduled_work(); 636 flush_scheduled_work();
636 637
637 mutex_lock(&tty->ldisc_mutex);
638 tty_lock(); 638 tty_lock();
639 mutex_lock(&tty->ldisc_mutex);
639 if (test_bit(TTY_HUPPED, &tty->flags)) { 640 if (test_bit(TTY_HUPPED, &tty->flags)) {
640 /* We were raced by the hangup method. It will have stomped 641 /* We were raced by the hangup method. It will have stomped
641 the ldisc data and closed the ldisc down */ 642 the ldisc data and closed the ldisc down */
@@ -782,7 +783,20 @@ void tty_ldisc_hangup(struct tty_struct *tty)
782 * Avoid racing set_ldisc or tty_ldisc_release 783 * Avoid racing set_ldisc or tty_ldisc_release
783 */ 784 */
784 mutex_lock(&tty->ldisc_mutex); 785 mutex_lock(&tty->ldisc_mutex);
785 tty_ldisc_halt(tty); 786
787 /*
788 * this is like tty_ldisc_halt, but we need to give up
789 * the BTM before calling cancel_delayed_work_sync,
790 * which may need to wait for another function taking the BTM
791 */
792 clear_bit(TTY_LDISC, &tty->flags);
793 tty_unlock();
794 cancel_delayed_work_sync(&tty->buf.work);
795 mutex_unlock(&tty->ldisc_mutex);
796
797 tty_lock();
798 mutex_lock(&tty->ldisc_mutex);
799
786 /* At this point we have a closed ldisc and we want to 800 /* At this point we have a closed ldisc and we want to
787 reopen it. We could defer this to the next open but 801 reopen it. We could defer this to the next open but
788 it means auditing a lot of other paths so this is 802 it means auditing a lot of other paths so this is
@@ -853,8 +867,10 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
853 * race with the set_ldisc code path. 867 * race with the set_ldisc code path.
854 */ 868 */
855 869
870 tty_unlock();
856 tty_ldisc_halt(tty); 871 tty_ldisc_halt(tty);
857 flush_scheduled_work(); 872 flush_scheduled_work();
873 tty_lock();
858 874
859 mutex_lock(&tty->ldisc_mutex); 875 mutex_lock(&tty->ldisc_mutex);
860 /* 876 /*