[openib-general] [PATCH] dont drop device reference before use (was Re: sdp: cant unload ib_ipoib module)

Michael S. Tsirkin mst at mellanox.co.il
Sun Aug 14 07:24:41 PDT 2005


Quoting r. Hal Rosenstock <halr at voltaire.com>:
> Subject: Re: sdp: cant unload ib_ipoib module
> 
> Hi Michael,
> 
> On Tue, 2005-08-09 at 08:46, Michael S. Tsirkin wrote:
> > ip_rt_put now looks right, but it looks like device_put is still done too early.
> 
> Any idea where it should be done ?

The following should finally fix the dev_put issue.
I think an extra dev_hold on a path lookup is not a big deal, and
helps make the code much simpler. Works fine, for me.
Hal, can you give it a whirl?

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,7 +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 net_device *dev = NULL;
 	struct rtable *rt;
 	int counter = 0;
 	int result = 0;
@@ -387,7 +387,7 @@ static void do_link_path_lookup(void *da
 	 * check for IB device or loopback, the later requires extra
 	 * handling.
 	 */
-	if (ARPHRD_INFINIBAND != rt->u.dst.neighbour->dev->type &&
+	if (rt->u.dst.neighbour->dev->type != ARPHRD_INFINIBAND &&
 	    !(rt->u.dst.neighbour->dev->flags & IFF_LOOPBACK)) {
 		result = -ENETUNREACH;
 		goto error;
@@ -402,23 +402,28 @@ static void do_link_path_lookup(void *da
 	 * In case of loopback find a valid IB device on which to
 	 * direct the loopback traffic.
 	 */
-	info->dev = ((rt->u.dst.neighbour->dev->flags & IFF_LOOPBACK) ?
-		     (loopback = ip_dev_find(rt->rt_src)) :
-		     rt->u.dst.neighbour->dev);
+	if (rt->u.dst.neighbour->dev->flags & IFF_LOOPBACK)
+		dev = ip_dev_find(rt->rt_src);
+	else {
+		dev = rt->u.dst.neighbour->dev;
+		dev_hold(dev);
+	}
 
 	info->gw  = rt->rt_gateway;
 	info->src = rt->rt_src;     /* true source IP address */
 
-	if (info->dev->flags & IFF_LOOPBACK)
-		while ((info->dev = dev_get_by_index(++counter))) {
-
-			dev_put(info->dev);
-			if (ARPHRD_INFINIBAND == info->dev->type &&
-			    (info->dev->flags & IFF_UP))
+	if (dev->flags & IFF_LOOPBACK) {
+		dev_put(dev);
+		while ((dev = dev_get_by_index(++counter))) {
+			if (dev->type == ARPHRD_INFINIBAND &&
+			    (dev->flags & IFF_UP))
 				break;
+			else
+				dev_put(dev);
 		}
+	}
 
-	if (!info->dev) {
+	if (!dev) {
 		sdp_dbg_warn(NULL, "No device for IB comm <%s:%08x:%08x>",
 			     rt->u.dst.neighbour->dev->name,
 			     rt->u.dst.neighbour->dev->flags,
@@ -429,20 +434,20 @@ static void do_link_path_lookup(void *da
 	/*
 	 * lookup local info.
 	 */
-	priv = info->dev->priv;
+	priv = dev->priv;
 
 	info->ca             = priv->ca;
 	info->port           = priv->port;
 	info->path.pkey      = cpu_to_be16(priv->pkey);
 	info->path.numb_path = 1;
 
-	memcpy(&info->path.sgid, info->dev->dev_addr + 4, sizeof(union ib_gid));
+	memcpy(&info->path.sgid, dev->dev_addr + 4, sizeof(union ib_gid));
 	/*
 	 * If the routing device is loopback save the device address of
 	 * the IB device which was found.
 	 */
 	if (rt->u.dst.neighbour->dev->flags & IFF_LOOPBACK) {
-		memcpy(&info->path.dgid, info->dev->dev_addr + 4,
+		memcpy(&info->path.dgid, dev->dev_addr + 4,
 		       sizeof(union ib_gid));
 
 		goto path;
@@ -466,10 +471,10 @@ arp:
 	arp_send(ARPOP_REQUEST,
 		 ETH_P_ARP,
 		 info->gw,
-		 info->dev,
+		 dev,
 		 info->src,
 		 NULL,
-		 info->dev->dev_addr,
+		 dev->dev_addr,
 		 NULL);
 	/*
 	 * start arp timer if it's not already going.
@@ -498,8 +503,8 @@ arp:
 
 	info->flags |= SDP_LINK_F_ARP;
 	queue_delayed_work(link_wq, &info->timer, info->arp_time);
-	if (loopback)
-		dev_put(loopback);
+	if (dev)
+		dev_put(dev);
 	ip_rt_put(rt);
 	return;
 path:
@@ -509,14 +514,14 @@ path:
 		goto error;
 	}
 done:
-	if (loopback)
-		dev_put(loopback);
+	if (dev)
+		dev_put(dev);
 	ip_rt_put(rt);
 	return;
 error:
 	sdp_path_info_destroy(info, result);
-	if (loopback)
-		dev_put(loopback);
+	if (dev)
+		dev_put(dev);
 	ip_rt_put(rt);
 }
 
@@ -690,7 +695,7 @@ static int sdp_link_arp_recv(struct sk_b
 
 	arp_hdr = (struct arphdr *)skb->nh.raw;
 
-	if (ARPHRD_INFINIBAND != dev->type ||
+	if (dev->type != ARPHRD_INFINIBAND ||
 	    (arp_hdr->ar_op != __constant_htons(ARPOP_REPLY) &&
 	     arp_hdr->ar_op != __constant_htons(ARPOP_REQUEST)))
 		goto done;
Index: linux-2.6.12.2/drivers/infiniband/ulp/sdp/sdp_link.h
===================================================================
--- linux-2.6.12.2.orig/drivers/infiniband/ulp/sdp/sdp_link.h
+++ linux-2.6.12.2/drivers/infiniband/ulp/sdp/sdp_link.h
@@ -59,8 +59,6 @@ struct sdp_path_info {
 
 	struct work_struct timer;   /* arp request timers. */
 
-	struct net_device     *dev; /* ipoib device */
-
 	struct sdp_path_info  *next; /* next element in path list. */
 	struct sdp_path_info **pext; /* previous next element in path list */
 


-- 
MST



More information about the general mailing list