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

Yossi Etigin yossi.openib at gmail.com
Fri May 22 10:34:57 PDT 2009


akepner at sgi.com wrote:
> On Fri, May 22, 2009 at 01:24:17PM +0300, Yossi Etigin wrote:
>> ...
>> 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); <-- deadlock here
>> +
>>  	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)
>>
> 
> This is essentially what I did first time around, but a deadlock on 
> the line marked above was quickly found. 
> 

Interesting... what does it deadlock with?
And what is the hole your fix leaves? If the (neigh!=NULL) check passes
with the spinlock held, shouldn't it be OK to list_del() it?

--Yossi




More information about the general mailing list