linux/net/rds
Eric Dumazet f064af1e50 net: fix a lockdep splat
We have for each socket :

One spinlock (sk_slock.slock)
One rwlock (sk_callback_lock)

Possible scenarios are :

(A) (this is used in net/sunrpc/xprtsock.c)
read_lock(&sk->sk_callback_lock) (without blocking BH)
<BH>
spin_lock(&sk->sk_slock.slock);
...
read_lock(&sk->sk_callback_lock);
...

(B)
write_lock_bh(&sk->sk_callback_lock)
stuff
write_unlock_bh(&sk->sk_callback_lock)

(C)
spin_lock_bh(&sk->sk_slock)
...
write_lock_bh(&sk->sk_callback_lock)
stuff
write_unlock_bh(&sk->sk_callback_lock)
spin_unlock_bh(&sk->sk_slock)

This (C) case conflicts with (A) :

CPU1 [A]                         CPU2 [C]
read_lock(callback_lock)
<BH>                             spin_lock_bh(slock)
<wait to spin_lock(slock)>
                                 <wait to write_lock_bh(callback_lock)>

We have one problematic (C) use case in inet_csk_listen_stop() :

local_bh_disable();
bh_lock_sock(child); // spin_lock_bh(&sk->sk_slock)
WARN_ON(sock_owned_by_user(child));
...
sock_orphan(child); // write_lock_bh(&sk->sk_callback_lock)

lockdep is not happy with this, as reported by Tetsuo Handa

It seems only way to deal with this is to use read_lock_bh(callbacklock)
everywhere.

Thanks to Jarek for pointing a bug in my first attempt and suggesting
this solution.

Reported-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Tested-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Jarek Poplawski <jarkao2@gmail.com>
Tested-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-09-24 22:26:10 -07:00
..
af_rds.c net: sk_sleep() helper 2010-04-20 16:37:13 -07:00
bind.c
cong.c
connection.c
ib_cm.c net/rds: Add missing mutex_unlock 2010-05-29 00:18:48 -07:00
ib_rdma.c
ib_recv.c
ib_ring.c
ib_send.c
ib_stats.c
ib_sysctl.c
ib.c
ib.h
info.c
info.h
iw_cm.c net/rds: Add missing mutex_unlock 2010-05-29 00:18:48 -07:00
iw_rdma.c
iw_recv.c
iw_ring.c
iw_send.c
iw_stats.c
iw_sysctl.c
iw.c
iw.h
Kconfig
loop.c
loop.h
Makefile
message.c
page.c
rdma_transport.c Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6 2010-04-27 12:49:13 -07:00
rdma_transport.h
rdma.c
rdma.h
rds.h net: sk_sleep() helper 2010-04-20 16:37:13 -07:00
recv.c rds: fix a leak of kernel memory 2010-08-18 23:40:03 -07:00
send.c net: sk_sleep() helper 2010-04-20 16:37:13 -07:00
stats.c
sysctl.c
tcp_connect.c net: fix a lockdep splat 2010-09-24 22:26:10 -07:00
tcp_listen.c net: fix a lockdep splat 2010-09-24 22:26:10 -07:00
tcp_recv.c net: fix a lockdep splat 2010-09-24 22:26:10 -07:00
tcp_send.c net: fix a lockdep splat 2010-09-24 22:26:10 -07:00
tcp_stats.c
tcp.c
tcp.h
threads.c
transport.c