[openib-general] neigh destructor work-around
Michael S. Tsirkin
mst at mellanox.co.il
Wed Mar 15 08:37:01 PST 2006
Roland, the following patch implements a work around for the
destructor issue for 2.6.16. Would you care to check it in, to svn only?
---
Work around for neighbour destructor issue for kernels < 2.6.17:
keep a global list of all ipoib neighbours. Use it in destructor to
1. Verify that this neighbour belongs to an ipoib device
2. Check that the neighbour is the last one to use the destructor,
if so reset the destructor pointer
Index: linux-2.6.15/drivers/infiniband/ulp/ipoib/ipoib.h
===================================================================
--- linux-2.6.15.orig/drivers/infiniband/ulp/ipoib/ipoib.h 2006-03-13 15:11:35.000000000 +0200
+++ linux-2.6.15/drivers/infiniband/ulp/ipoib/ipoib.h 2006-03-13 15:26:41.000000000 +0200
@@ -222,6 +222,9 @@ struct ipoib_neigh {
struct neighbour *neighbour;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
+ struct list_head all_neigh_list;
+#endif
struct list_head list;
struct list_head dev_neigh_list;
};
Index: linux-2.6.15/drivers/infiniband/ulp/ipoib/ipoib_main.c
===================================================================
--- linux-2.6.15.orig/drivers/infiniband/ulp/ipoib/ipoib_main.c 2006-03-13 15:26:14.000000000 +0200
+++ linux-2.6.15/drivers/infiniband/ulp/ipoib/ipoib_main.c 2006-03-13 15:29:26.000000000 +0200
@@ -73,6 +73,11 @@ static const u8 ipv4_bcast_addr[] = {
struct workqueue_struct *ipoib_workqueue;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
+static spinlock_t ipoib_all_neigh_list_lock;
+static LIST_HEAD(ipoib_all_neigh_list);
+#endif
+
static void ipoib_add_one(struct ib_device *device);
static void ipoib_remove_one(struct ib_device *device);
@@ -747,6 +752,19 @@ static void ipoib_neigh_destructor(struc
unsigned long flags;
struct ipoib_ah *ah = NULL;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
+ 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;
+#endif
+
ipoib_dbg(priv,
"neigh_destructor for %06x " IPOIB_GID_FMT "\n",
be32_to_cpup((__be32 *) n->ha),
@@ -782,7 +800,10 @@ struct ipoib_neigh *ipoib_neigh_alloc(st
*to_ipoib_neigh(neighbour) = neigh;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
+ 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);
#endif
return neigh;
@@ -791,7 +812,16 @@ struct ipoib_neigh *ipoib_neigh_alloc(st
void ipoib_neigh_free(struct ipoib_neigh *neigh)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
+ 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;
+
neigh->neighbour->ops->destructor = NULL;
+found:
+ spin_unlock(&ipoib_all_neigh_list_lock);
#endif
*to_ipoib_neigh(neigh->neighbour) = NULL;
@@ -1168,6 +1198,10 @@ static int __init ipoib_init_module(void
goto err_fs;
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
+ spin_lock_init(&ipoib_all_neigh_list_lock);
+#endif
+
ret = ib_register_client(&ipoib_client);
if (ret)
goto err_wq;
--
Michael S. Tsirkin
Staff Engineer, Mellanox Technologies
More information about the general
mailing list