kernel-fxtec-pro1x/drivers/tty
Sebastian Andrzej Siewior 852e4a8152 tty: don't deadlock while flushing workqueue
Since commit 89c8d91e31 ("tty: localise the lock") I see a dead lock
in one of my dummy_hcd + g_nokia test cases. The first run was usually
okay, the second often resulted in a splat by lockdep and the third was
usually a dead lock.
Lockdep complained about tty->hangup_work and tty->legacy_mutex taken
both ways:
| ======================================================
| [ INFO: possible circular locking dependency detected ]
| 3.7.0-rc6+ #204 Not tainted
| -------------------------------------------------------
| kworker/2:1/35 is trying to acquire lock:
|  (&tty->legacy_mutex){+.+.+.}, at: [<c14051e6>] tty_lock_nested+0x36/0x80
|
| but task is already holding lock:
|  ((&tty->hangup_work)){+.+...}, at: [<c104f6e4>] process_one_work+0x124/0x5e0
|
| which lock already depends on the new lock.
|
| the existing dependency chain (in reverse order) is:
|
| -> #2 ((&tty->hangup_work)){+.+...}:
|        [<c107fe74>] lock_acquire+0x84/0x190
|        [<c104d82d>] flush_work+0x3d/0x240
|        [<c12e6986>] tty_ldisc_flush_works+0x16/0x30
|        [<c12e7861>] tty_ldisc_release+0x21/0x70
|        [<c12e0dfc>] tty_release+0x35c/0x470
|        [<c1105e28>] __fput+0xd8/0x270
|        [<c1105fcd>] ____fput+0xd/0x10
|        [<c1051dd9>] task_work_run+0xb9/0xf0
|        [<c1002a51>] do_notify_resume+0x51/0x80
|        [<c140550a>] work_notifysig+0x35/0x3b
|
| -> #1 (&tty->legacy_mutex/1){+.+...}:
|        [<c107fe74>] lock_acquire+0x84/0x190
|        [<c140276c>] mutex_lock_nested+0x6c/0x2f0
|        [<c14051e6>] tty_lock_nested+0x36/0x80
|        [<c1405279>] tty_lock_pair+0x29/0x70
|        [<c12e0bb8>] tty_release+0x118/0x470
|        [<c1105e28>] __fput+0xd8/0x270
|        [<c1105fcd>] ____fput+0xd/0x10
|        [<c1051dd9>] task_work_run+0xb9/0xf0
|        [<c1002a51>] do_notify_resume+0x51/0x80
|        [<c140550a>] work_notifysig+0x35/0x3b
|
| -> #0 (&tty->legacy_mutex){+.+.+.}:
|        [<c107f3c9>] __lock_acquire+0x1189/0x16a0
|        [<c107fe74>] lock_acquire+0x84/0x190
|        [<c140276c>] mutex_lock_nested+0x6c/0x2f0
|        [<c14051e6>] tty_lock_nested+0x36/0x80
|        [<c140523f>] tty_lock+0xf/0x20
|        [<c12df8e4>] __tty_hangup+0x54/0x410
|        [<c12dfcb2>] do_tty_hangup+0x12/0x20
|        [<c104f763>] process_one_work+0x1a3/0x5e0
|        [<c104fec9>] worker_thread+0x119/0x3a0
|        [<c1055084>] kthread+0x94/0xa0
|        [<c140ca37>] ret_from_kernel_thread+0x1b/0x28
|
|other info that might help us debug this:
|
|Chain exists of:
|  &tty->legacy_mutex --> &tty->legacy_mutex/1 --> (&tty->hangup_work)
|
| Possible unsafe locking scenario:
|
|       CPU0                    CPU1
|       ----                    ----
|  lock((&tty->hangup_work));
|                               lock(&tty->legacy_mutex/1);
|                               lock((&tty->hangup_work));
|  lock(&tty->legacy_mutex);
|
| *** DEADLOCK ***

Before the path mentioned tty_ldisc_release() look like this:

|	tty_ldisc_halt(tty);
|	tty_ldisc_flush_works(tty);
|	tty_lock();

As it can be seen, it first flushes the workqueue and then grabs the
tty_lock. Now we grab the lock first:

|	tty_lock_pair(tty, o_tty);
|	tty_ldisc_halt(tty);
|	tty_ldisc_flush_works(tty);

so lockdep's complaint seems valid.

The earlier version of this patch took the ldisc_mutex since the other
user of tty_ldisc_flush_works() (tty_set_ldisc()) did this.
Peter Hurley then said that it is should not be requried. Since it
wasn't done earlier, I dropped this part.
The code under tty_ldisc_kill() was executed earlier with the tty lock
taken so it is taken again.

I was able to reproduce the deadlock on v3.8-rc1, this patch fixes the
problem in my testcase. I didn't notice any problems so far.

Cc: Alan Cox <alan@linux.intel.com>
Cc: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-01-15 23:07:15 -08:00
..
hvc TTY: hvsi: use for_each_compatible_node() macro 2013-01-15 23:00:43 -08:00
ipwireless TTY: switch tty_flip_buffer_push 2013-01-15 22:30:15 -08:00
serial serial: 8250_dw: Enable DMA support with ACPI 2013-01-15 23:03:00 -08:00
vt TTY: switch tty_schedule_flip 2013-01-15 22:43:15 -08:00
amiserial.c TTY: switch tty_flip_buffer_push 2013-01-15 22:30:15 -08:00
bfin_jtag_comm.c TTY: switch tty_flip_buffer_push 2013-01-15 22:30:15 -08:00
cyclades.c cyclades: push down tty_port_tty_get 2013-01-15 22:43:15 -08:00
ehv_bytechan.c TTY: switch tty_flip_buffer_push 2013-01-15 22:30:15 -08:00
isicom.c TTY: switch tty_flip_buffer_push 2013-01-15 22:30:15 -08:00
Kconfig Merge branch 'for-upstream' of http://github.com/agraf/linux-2.6 into queue 2012-10-10 19:03:54 -03:00
Makefile tty/powerpc: introduce the ePAPR embedded hypervisor byte channel driver 2011-08-23 10:32:56 -07:00
moxa.c TTY: switch tty_schedule_flip 2013-01-15 22:43:15 -08:00
moxa.h
mxser.c TTY: switch tty_flip_buffer_push 2013-01-15 22:30:15 -08:00
mxser.h Fix common misspellings 2011-03-31 11:26:23 -03:00
n_gsm.c Revert "n_gsm.c: add tx_lock in gsm_send" 2013-01-15 22:48:15 -08:00
n_hdlc.c Remove all #inclusions of asm/system.h 2012-03-28 18:30:03 +01:00
n_r3964.c tty: localise the lock 2012-08-10 12:55:47 -07:00
n_tracerouter.c n_tracerouter and n_tracesink ldisc additions. 2011-05-13 16:31:00 -07:00
n_tracesink.c n_tracerouter and n_tracesink ldisc additions. 2011-05-13 16:31:00 -07:00
n_tracesink.h n_tracerouter and n_tracesink ldisc additions. 2011-05-13 16:31:00 -07:00
n_tty.c tty: add missing newlines to WARN_RATELIMIT 2012-10-25 11:30:27 -07:00
nozomi.c TTY: nozomi, remove dead code 2013-01-15 22:43:16 -08:00
pty.c TTY: do not reset master's packet mode 2013-01-15 22:49:36 -08:00
rocket.c tty: add parenthesis to macro POLL_PERIOD in rocket.c 2013-01-15 22:49:36 -08:00
rocket.h
rocket_int.h
synclink.c TTY: switch tty_flip_buffer_push 2013-01-15 22:30:15 -08:00
synclink_gt.c TTY: synclink, remove unneeded tests 2013-01-15 22:43:15 -08:00
synclinkmp.c TTY: synclink, remove unneeded tests 2013-01-15 22:43:15 -08:00
sysrq.c mm, oom: ensure sysrq+f always passes valid zonelist 2012-11-15 17:13:48 -08:00
tty_audit.c TTY: audit, stop accessing tty->icount 2012-10-22 16:50:54 -07:00
tty_buffer.c TTY: switch tty_schedule_flip 2013-01-15 22:43:15 -08:00
tty_io.c tty: Fix comments that reference BKL, eventd, old paths 2013-01-15 21:57:44 -08:00
tty_ioctl.c tty: pty - Move TIOCPKT handling into pty.c 2012-10-25 12:07:18 -07:00
tty_ldisc.c tty: don't deadlock while flushing workqueue 2013-01-15 23:07:15 -08:00
tty_mutex.c tty: tty_mutex.c: Fixed coding style warning (using printk) 2012-10-24 11:34:51 -07:00
tty_port.c TTY: introduce tty_port_destroy 2012-11-15 17:20:58 -08:00