[openib-general] Re: sdp: cant unload ib_ipoib module

Michael S. Tsirkin mst at mellanox.co.il
Sun Aug 7 08:46:33 PDT 2005


> > After running ttcp.aio.x multiple times, I am seeing
> > these messages in dmesg:
> > 
> > unregister_netdevice: waiting for ib0 to become free. Usage count = 2
> > 
> > and ipoib cant be unloaded.
> 
Quoting Hal Rosenstock <halr at voltaire.com>:
> This was reported back a while ago. The simplest scenario I have found to
> reproduce this is as follows:

Quoting r. Libor Michalek <limichal at cisco.com>:
> Michael,
> 
>   I remember this problem from the last time Hal mentioned it, I had
> just forgotten about it. I'm almost certain this is being caused by
> a reference counter incremented in the sdp address resolution code
> that is never decremented. In sdp_link.c:do_link_path_lookup() we get
> the route table entry using ip_route_output_key(), which I believe
> takes out a reference, and that reference should be returned using
> ip_rt_put() which we never do.

OK, I grew tired of rebooting and went over sdp_link.c looking for stale
references.
Given how the old code doesnt ever do ip_rt_put in most cases, I dont really
understand why dont more people see this problem.

With the patch below I can unload ipoib after running sdp tests.

Hal, could you verify that this patch helps you, too?

--- 

Drop net_device and rtable references after path lookup is done.

Signed-off-by: Michael S. Tsirkin <mst at mellanox.co.il>

Index: linux-2.6.12.2/drivers/infiniband/ulp/sdp/sdp_link.c
===================================================================
--- linux-2.6.12.2.orig/drivers/infiniband/ulp/sdp/sdp_link.c
+++ linux-2.6.12.2/drivers/infiniband/ulp/sdp/sdp_link.c
@@ -327,6 +327,7 @@ static void do_link_path_lookup(void *da
 {
 	struct sdp_path_info *info = data;
 	struct ipoib_dev_priv *priv;
+	struct net_device *loopback = NULL;
 	struct rtable *rt;
 	int counter = 0;
 	int result = 0;
@@ -360,6 +361,7 @@ static void do_link_path_lookup(void *da
 
 	result = ip_route_output_key(&rt, &fl);
 	if (result < 0 || !rt) {
+		rt = NULL;
 		sdp_dbg_warn(NULL, "Error <%d> routing <%08x:%08x> (%d)",
 			     result, info->dst, info->src, info->dif);
 		goto error;
@@ -368,7 +370,6 @@ static void do_link_path_lookup(void *da
 	 * check route flags
 	 */
 	if ((RTCF_MULTICAST|RTCF_BROADCAST) & rt->rt_flags) {
-		ip_rt_put(rt);
 		result = -ENETUNREACH;
 		goto error;
 	}
@@ -402,7 +403,8 @@ static void do_link_path_lookup(void *da
 	 * direct the loopback traffic.
 	 */
 	info->dev = ((rt->u.dst.neighbour->dev->flags & IFF_LOOPBACK) ?
-		     ip_dev_find(rt->rt_src) : rt->u.dst.neighbour->dev);
+		     (loopback = ip_dev_find(rt->rt_src)) :
+		     rt->u.dst.neighbour->dev);
 
 	info->gw  = rt->rt_gateway;
 	info->src = rt->rt_src;     /* true source IP address */
@@ -500,7 +502,9 @@ arp:
 
 	info->flags |= SDP_LINK_F_ARP;
 	queue_delayed_work(link_wq, &info->timer, info->arp_time);
-
+	if (loopback)
+		dev_put(loopback);
+	ip_rt_put(rt);
 	return;
 path:
 	result = sdp_link_path_rec_get(info);
@@ -509,9 +513,15 @@ path:
 		goto error;
 	}
 done:
+	if (loopback)
+		dev_put(loopback);
+	ip_rt_put(rt);
 	return;
 error:
 	sdp_path_info_destroy(info, result);
+	if (loopback)
+		dev_put(loopback);
+	ip_rt_put(rt);
 }
 
 /*


-- 
MST



More information about the general mailing list