blob: 1f66dd96f6b136ddd82bcc03efed92a22ec5d529 [file] [log] [blame]
From 15490ab9d58994558ce5de0116c20fc8ac32f68f Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Fri, 11 Oct 2013 16:15:08 +0200
Subject: [PATCH] tty: ldisc: drop the raw lock earlier
Luis Claudio R. Goncalves reported the following:
|BUG: sleeping function called from invalid context at kernel/rtmutex.c:659
|in_atomic(): 1, irqs_disabled(): 1, pid: 188, name: plymouthd
|3 locks held by plymouthd/188:
| #0: (&tty->legacy_mutex){......}, at: [<ffffffff816528d0>] tty_lock_nested+0x40/0x90
| #1: (&tty->ldisc_mutex){......}, at: [<ffffffff8139b482>] tty_ldisc_hangup+0x152/0x300
| #2: (tty_ldisc_lock){......}, at: [<ffffffff8139a9c2>] tty_ldisc_reinit+0x72/0x130
|Preemption disabled at:[<ffffffff8139a9c2>] tty_ldisc_reinit+0x72/0x130
|CPU: 2 PID: 188 Comm: plymouthd Not tainted 3.10.10-rt7+ #6
|Call Trace:
| [<ffffffff8164b790>] dump_stack+0x19/0x1b
| [<ffffffff8107e62f>] __might_sleep+0xff/0x170
| [<ffffffff81651ac4>] rt_spin_lock+0x24/0x60
| [<ffffffff81130984>] free_hot_cold_page+0xb4/0x3c0
| [<ffffffff81178209>] ?unfreeze_partials.isra.42+0x229/0x2b0
| [<ffffffff81130dc7>] __free_pages+0x47/0x70
| [<ffffffff81130fb2>] __free_memcg_kmem_pages+0x22/0x50
| [<ffffffff81177528>] __free_slab+0xe8/0x1e0
| [<ffffffff81177654>] free_delayed+0x34/0x50
| [<ffffffff81649633>] __slab_free+0x273/0x36b
| [<ffffffff81178794>] kfree+0x1c4/0x210
| [<ffffffff8139a9f5>] tty_ldisc_reinit+0xa5/0x130
| [<ffffffff8139b49f>] tty_ldisc_hangup+0x16f/0x300
| [<ffffffff81392136>] __tty_hangup+0x346/0x460
| [<ffffffff81392260>] tty_vhangup+0x10/0x20
| [<ffffffff8139d6e1>] pty_close+0x131/0x180
| [<ffffffff813936ad>] tty_release+0x11d/0x5f0
It looks safe to drop the tty_ldisc_lock lock before module_put() and
kree() so do it.
Cc: stable-rt@vger.kernel.org
Reported-By: Luis Claudio R. Goncalves <lclaudio@uudg.org>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
drivers/tty/tty_ldisc.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index 1afe192..bc4ffe4 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -197,9 +197,10 @@ static inline void tty_ldisc_put(struct tty_ldisc *ld)
WARN_ON(!atomic_dec_and_test(&ld->users));
ld->ops->refcount--;
+ raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+
module_put(ld->ops->owner);
kfree(ld);
- raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
}
static void *tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
--
1.8.4.rc3