[openib-general] IPoIB descructor for 2.6.16-stable?

Michael S. Tsirkin mst at mellanox.co.il
Wed Apr 5 04:52:32 PDT 2006


Roland,
given that the cleaner backport from 2.6.17 got voted down from 2.6.16,
how about pushing a work-around from subversion in there?
Something along the lines of the patch below?

Is this small/obvious enough to be considered for stable? What do you think?

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

Index: linux-2.6.16.1/drivers/infiniband/ulp/ipoib/ipoib_main.c
===================================================================
--- linux-2.6.16.1.orig/drivers/infiniband/ulp/ipoib/ipoib_main.c	2006-03-28 08:49:02.000000000 +0200
+++ linux-2.6.16.1/drivers/infiniband/ulp/ipoib/ipoib_main.c	2006-04-05 11:30:35.000000000 +0300
@@ -73,6 +73,9 @@ static const u8 ipv4_bcast_addr[] = {
 
 struct workqueue_struct *ipoib_workqueue;
 
+static DEFINE_SPINLOCK(ipoib_all_neigh_list_lock);
+static LIST_HEAD(ipoib_all_neigh_list);
+
 static void ipoib_add_one(struct ib_device *device);
 static void ipoib_remove_one(struct ib_device *device);
 
@@ -246,8 +249,8 @@ static void path_free(struct net_device 
 		 */
 		if (neigh->ah)
 			ipoib_put_ah(neigh->ah);
+		ipoib_neigh_cleanup(neigh);
 		*to_ipoib_neigh(neigh->neighbour) = NULL;
-		neigh->neighbour->ops->destructor = NULL;
 		kfree(neigh);
 	}
 
@@ -486,6 +489,7 @@ static void neigh_add_path(struct sk_buf
 	skb_queue_head_init(&neigh->queue);
 	neigh->neighbour = skb->dst->neighbour;
 	*to_ipoib_neigh(skb->dst->neighbour) = neigh;
+	ipoib_neigh_setup(neigh)
 
 	/*
 	 * We can only be called from ipoib_start_xmit, so we're
@@ -528,9 +532,9 @@ static void neigh_add_path(struct sk_buf
 	return;
 
 err:
+	ipoib_neigh_cleanup(neigh);
 	*to_ipoib_neigh(skb->dst->neighbour) = NULL;
 	list_del(&neigh->list);
-	neigh->neighbour->ops->destructor = NULL;
 	kfree(neigh);
 
 	++priv->stats.tx_dropped;
@@ -747,6 +751,17 @@ static void ipoib_neigh_destructor(struc
 	unsigned long flags;
 	struct ipoib_ah *ah = NULL;
 
+	struct ipoib_neigh *tn, *nn = NULL;
+	spin_lock(&ipoib_all_neigh_list_lock);
+	list_for_each_entry(tn, &ipoib_all_neigh_list, all_neigh_list)
+		if (tn->neighbour == n) {
+			nn = tn;
+			break;
+		}
+	spin_unlock(&ipoib_all_neigh_list_lock);
+	if (!nn)
+		return;
+
 	ipoib_dbg(priv,
 		  "neigh_destructor for %06x " IPOIB_GID_FMT "\n",
 		  be32_to_cpup((__be32 *) n->ha),
@@ -759,6 +774,7 @@ static void ipoib_neigh_destructor(struc
 		if (neigh->ah)
 			ah = neigh->ah;
 		list_del(&neigh->list);
+		ipoib_neigh_cleanup(neigh);
 		*to_ipoib_neigh(n) = NULL;
 		kfree(neigh);
 	}
@@ -769,23 +785,31 @@ static void ipoib_neigh_destructor(struc
 		ipoib_put_ah(ah);
 }
 
-static int ipoib_neigh_setup(struct neighbour *neigh)
+void ipoib_neigh_setup(struct ipoib_neigh *neigh)
 {
 	/*
 	 * Is this kosher?  I can't find anybody in the kernel that
 	 * sets neigh->destructor, so we should be able to set it here
 	 * without trouble.
 	 */
-	neigh->ops->destructor = ipoib_neigh_destructor;
-
-	return 0;
+	spin_lock(&ipoib_all_neigh_list_lock);
+	list_add_tail(&neigh->all_neigh_list, &ipoib_all_neigh_list);
+	neigh->neighbour->ops->destructor = ipoib_neigh_destructor;
+	spin_unlock(&ipoib_all_neigh_list_lock);
 }
 
-static int ipoib_neigh_setup_dev(struct net_device *dev, struct neigh_parms *parms)
-{
-	parms->neigh_setup = ipoib_neigh_setup;
+int ipoib_neigh_cleanup(struct ipoib_neigh *neigh)
+{
+	struct ipoib_neigh *nn;
+	spin_lock(&ipoib_all_neigh_list_lock);
+	list_del(&neigh->all_neigh_list);
+	list_for_each_entry(nn, &ipoib_all_neigh_list, all_neigh_list)
+		if (nn->neighbour->ops == neigh->neighbour->ops)
+			goto found;
 
-	return 0;
+	neigh->neighbour->ops->destructor = NULL;
+found:
+	spin_unlock(&ipoib_all_neigh_list_lock);
 }
 
 int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
@@ -861,7 +885,6 @@ static void ipoib_setup(struct net_devic
 	dev->tx_timeout 	 = ipoib_timeout;
 	dev->hard_header 	 = ipoib_hard_header;
 	dev->set_multicast_list  = ipoib_set_mcast_list;
-	dev->neigh_setup         = ipoib_neigh_setup_dev;
 
 	dev->watchdog_timeo 	 = HZ;
 
Index: linux-2.6.16.1/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
===================================================================
--- linux-2.6.16.1.orig/drivers/infiniband/ulp/ipoib/ipoib_multicast.c	2006-03-28 08:49:02.000000000 +0200
+++ linux-2.6.16.1/drivers/infiniband/ulp/ipoib/ipoib_multicast.c	2006-04-05 11:30:57.000000000 +0300
@@ -114,8 +114,8 @@ static void ipoib_mcast_free(struct ipoi
 		 */
 		if (neigh->ah)
 			ipoib_put_ah(neigh->ah);
+		ipoib_neigh_cleanup(neigh)
 		*to_ipoib_neigh(neigh->neighbour) = NULL;
-		neigh->neighbour->ops->destructor = NULL;
 		kfree(neigh);
 	}
 
@@ -766,6 +766,7 @@ out:
 				neigh->ah  	= mcast->ah;
 				neigh->neighbour = skb->dst->neighbour;
 				*to_ipoib_neigh(skb->dst->neighbour) = neigh;
+				ipoib_neigh_setup(neigh)
 				list_add_tail(&neigh->list, &mcast->neigh_list);
 			}
 		}

-- 
MST



More information about the general mailing list