mac80211: mesh: flush paths outside of plink lock
authorBob Copeland <me@bobcopeland.com>
Sat, 26 Mar 2016 15:27:19 +0000 (11:27 -0400)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 5 Apr 2016 19:34:54 +0000 (21:34 +0200)
commite596af827960c41a6051d4e719bafcfb7da11b64
tree6f29fda7c51fd24fb943990a3c32846829ad45ec
parent0371a08fbb3e557f19db41e47a199ad8300c9c97
mac80211: mesh: flush paths outside of plink lock

Lockdep warned of a lock dependency between the mesh_plink lock
and the internal lock for the rhashtable.  The problem is that
the rhashtable code uses a spin lock with softirqs enabled, while
mesh_plink_timer executes a walk (to flush paths on a state change)
inside a softirq with the plink lock held.

This leads to the following deadlock if the timer fires while rht
lock is held on this CPU, and plink lock is held on another CPU:

   CPU0                         CPU1
   ----                         ----
   lock(&(&ht->lock)->rlock);
                                local_irq_disable();
                                lock(&(&sta->mesh->plink_lock)->rlock);
                                lock(&(&ht->lock)->rlock);
   <Interrupt>
   lock(&(&sta->mesh->plink_lock)->rlock);
   *** DEADLOCK ***

Fix by waiting until we drop the plink lock to flush paths.

Fixes: d48a1b7cd439 ("mac80211: mesh: convert path table to rhashtable")
Signed-off-by: Bob Copeland <me@bobcopeland.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/mesh_plink.c