[ofa-general] [RFC] ipoib: avoid using stale ipoib_neigh* in ipoib_neigh_cleanup()

Yossi Etigin yossi.openib at gmail.com
Fri May 22 03:24:17 PDT 2009


akepner at sgi.com wrote:
> On Thu, May 21, 2009 at 08:32:22AM +0300, Or Gerlitz wrote:
>> ....
>>> Pid: 0, comm: swapper Tainted: G     U 2.6.16.54-0.2.5-smp 
>> its very likely that the problem you face in 2.6.16 was fixed by the 
>> commit I pointed on in my previous reply on this thread.
>>
> 
> Hmmm, it's not obvious to me that that commit 
> (ecbb416939da77c0d107409976499724baddce7b) would be relevant 
> to the bug that I mentioned earlier. 
> 

So, ipoib tries to list_del(neigh) twice because the second time
the condition (neigh != NULL) is not protected with a lock.
How about this:

diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index ab2c192..993b5a7 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -845,23 +845,24 @@ static void ipoib_neigh_cleanup(struct neighbour *n)
 	unsigned long flags;
 	struct ipoib_ah *ah = NULL;
 
+	spin_lock_irqsave(&priv->lock, flags);
+
 	neigh = *to_ipoib_neigh(n);
 	if (neigh)
 		priv = netdev_priv(neigh->dev);
 	else
-		return;
+		goto out;
 	ipoib_dbg(priv,
 		  "neigh_cleanup for %06x %pI6\n",
 		  IPOIB_QPN(n->ha),
 		  n->ha + 4);
 
-	spin_lock_irqsave(&priv->lock, flags);
-
 	if (neigh->ah)
 		ah = neigh->ah;
 	list_del(&neigh->list);
 	ipoib_neigh_free(n->dev, neigh);
 
+out:
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	if (ah)




More information about the general mailing list