IPoIB: Fix deadlock on RTNL between bcast join comp and ipoib_stop()
authorYossi Etigin <yossi.openib@gmail.com>
Tue, 16 Sep 2008 18:57:45 +0000 (11:57 -0700)
committerRoland Dreier <rolandd@cisco.com>
Tue, 16 Sep 2008 18:57:45 +0000 (11:57 -0700)
commite8224e4b804b4fd26723191c1891101a5959bb8a
tree94aa1274989fca8154bd3912d5f73239e705e7a3
parent1941246dd98089dd637f44d3bd4f6cc1c61aa9e4
IPoIB: Fix deadlock on RTNL between bcast join comp and ipoib_stop()

Taking rtnl_lock in ipoib_mcast_join_complete() causes a deadlock with
ipoib_stop().  We avoid it by scheduling the piece of code that takes
the lock on ipoib_workqueue instead of executing it directly.  This
works because we only flush the ipoib_workqueue with the RTNL not held.

The deadlock happens because ipoib_stop() calls ipoib_ib_dev_down()
which calls ipoib_mcast_dev_flush(), which calls ipoib_mcast_free(),
which calls ipoib_mcast_leave(). The latter calls
ib_sa_free_multicast(), and this waits until the multicast completion
handler finishes.  This handler is ipoib_mcast_join_complete(), which
waits for the rtnl_lock(), which was already taken by ipoib_stop().

This bug was introduced in commit a77a57a1 ("IPoIB: Fix deadlock on
RTNL in ipoib_stop()").

Signed-off-by: Yossi Etigin <yosefe@voltaire.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c