diff options
author | Jiri Kosina <jkosina@suse.cz> | 2007-03-07 23:41:18 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-03-08 10:38:21 -0500 |
commit | b40df5743ee8aed8674edbbb77b8fd3c8c7a747f (patch) | |
tree | ea10376ffa9a1a26e91cfca075761828c9b54623 | |
parent | 47c51dff4af25341c575e5089dbb92d61ac69cdf (diff) |
[PATCH] bluetooth: fix socket locking in hci_sock_dev_event()
[Bluetooth] Fix socket locking in hci_sock_dev_event()
hci_sock_dev_event() uses bh_lock_sock() to lock the socket lock.
This is not deadlock-safe against locking of the same socket lock in
l2cap_connect_cfm() from softirq context. In addition to that,
hci_sock_dev_event() doesn't seem to be called from softirq context,
so it is safe to use lock_sock()/release_sock() instead.
The lockdep warning can be triggered on my T42p simply by switching
the Bluetooth off by the keyboard button.
=================================
[ INFO: inconsistent lock state ]
2.6.21-rc2 #4
---------------------------------
inconsistent {in-softirq-W} -> {softirq-on-W} usage.
khubd/156 [HC0[0]:SC0[0]:HE1:SE1] takes:
(slock-AF_BLUETOOTH){-+..}, at: [<e0ca5520>] hci_sock_dev_event+0xa8/0xc5 [bluetooth]
{in-softirq-W} state was registered at:
[<c012d1db>] mark_lock+0x59/0x414
[<e0cef688>] l2cap_connect_cfm+0x4e/0x11f [l2cap]
[<c012dfd7>] __lock_acquire+0x3e5/0xb99
[<e0cef688>] l2cap_connect_cfm+0x4e/0x11f [l2cap]
[<c012e7f2>] lock_acquire+0x67/0x81
[<e0cef688>] l2cap_connect_cfm+0x4e/0x11f [l2cap]
[<c036ee72>] _spin_lock+0x29/0x34
[<e0cef688>] l2cap_connect_cfm+0x4e/0x11f [l2cap]
[<e0cef688>] l2cap_connect_cfm+0x4e/0x11f [l2cap]
[<e0ca17c3>] hci_send_cmd+0x126/0x14f [bluetooth]
[<e0ca4ce4>] hci_event_packet+0x729/0xebd [bluetooth]
[<e0ca205b>] hci_rx_task+0x2a/0x20f [bluetooth]
[<e0ca209d>] hci_rx_task+0x6c/0x20f [bluetooth]
[<c012d7be>] trace_hardirqs_on+0x10d/0x14e
[<c011ac85>] tasklet_action+0x3d/0x68
[<c011abba>] __do_softirq+0x41/0x92
[<c011ac32>] do_softirq+0x27/0x3d
[<c0105134>] do_IRQ+0x7b/0x8f
[<c0103dec>] common_interrupt+0x24/0x34
[<c0103df6>] common_interrupt+0x2e/0x34
[<c0248e65>] acpi_processor_idle+0x1b3/0x34a
[<c0248e68>] acpi_processor_idle+0x1b6/0x34a
[<c010232b>] cpu_idle+0x39/0x4e
[<c04bab0c>] start_kernel+0x372/0x37a
[<c04ba42b>] unknown_bootoption+0x0/0x202
[<ffffffff>] 0xffffffff
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | net/bluetooth/hci_sock.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index f928d2b2a17d..71f5cfbbebb8 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
@@ -656,7 +656,7 @@ static int hci_sock_dev_event(struct notifier_block *this, unsigned long event, | |||
656 | /* Detach sockets from device */ | 656 | /* Detach sockets from device */ |
657 | read_lock(&hci_sk_list.lock); | 657 | read_lock(&hci_sk_list.lock); |
658 | sk_for_each(sk, node, &hci_sk_list.head) { | 658 | sk_for_each(sk, node, &hci_sk_list.head) { |
659 | bh_lock_sock(sk); | 659 | lock_sock(sk); |
660 | if (hci_pi(sk)->hdev == hdev) { | 660 | if (hci_pi(sk)->hdev == hdev) { |
661 | hci_pi(sk)->hdev = NULL; | 661 | hci_pi(sk)->hdev = NULL; |
662 | sk->sk_err = EPIPE; | 662 | sk->sk_err = EPIPE; |
@@ -665,7 +665,7 @@ static int hci_sock_dev_event(struct notifier_block *this, unsigned long event, | |||
665 | 665 | ||
666 | hci_dev_put(hdev); | 666 | hci_dev_put(hdev); |
667 | } | 667 | } |
668 | bh_unlock_sock(sk); | 668 | release_sock(sk); |
669 | } | 669 | } |
670 | read_unlock(&hci_sk_list.lock); | 670 | read_unlock(&hci_sk_list.lock); |
671 | } | 671 | } |