[openib-general] [PATCH applied] sdp_link locking

Michael S. Tsirkin mst at mellanox.co.il
Thu Sep 1 05:50:45 PDT 2005


The following patch adds locking to sdp_link.
It does not yet include request cancellation,
and the workqueue handling code also seems buggy
(cancels must flush workqueue, and ideally we wouldnt need
a separate workqueue at all).

---

Add locking to sdp link code.

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	2005-09-01 17:35:49.000000000 +0300
+++ linux-2.6.12.2/drivers/infiniband/ulp/sdp/sdp_link.c	2005-09-01 17:38:44.000000000 +0300
@@ -128,6 +128,7 @@ struct sdp_link_arp {
 static kmem_cache_t *wait_cache;
 static kmem_cache_t *info_cache;
 
+static DECLARE_MUTEX(sdp_link_mutex);
 static LIST_HEAD(info_list);
 
 static struct workqueue_struct *link_wq;
@@ -150,7 +151,7 @@ static u64 path_lookup_id;
 /*
  * proto
  */
-static void do_link_path_lookup(void *data);
+static void retry_link_path_lookup(void *);
 
 /*
  * sdp_link_path_complete - generate a path record completion for user
@@ -219,8 +220,8 @@ static struct sdp_path_info *sdp_path_in
 	info->arp_time = SDP_LINK_ARP_TIME_MIN;
 
 	INIT_LIST_HEAD(&info->wait_list);
+	INIT_WORK(&info->timer, retry_link_path_lookup, info);
 	list_add(&info->info_list, &info_list);
-	INIT_WORK(&info->timer, do_link_path_lookup, info);
 
 	return info;
 }
@@ -252,6 +253,8 @@ static void sdp_link_path_rec_done(int s
 	struct sdp_path_wait *sweep;
 	int result;
 
+	down(&sdp_link_mutex);
+
 	info->query = NULL;
 
 	sdp_dbg_data(NULL, "Path Record status <%d>", status);
@@ -301,6 +304,7 @@ static void sdp_link_path_rec_done(int s
 			sdp_path_info_destroy(info, result);
 		}
 	}
+	up(&sdp_link_mutex);
 }
 
 /*
@@ -345,9 +349,8 @@ static int sdp_link_path_rec_get(struct 
 /*
  * do_link_path_lookup - resolve an ip address to a path record
  */
-static void do_link_path_lookup(void *data)
+static void do_link_path_lookup(struct sdp_path_info *info)
 {
-	struct sdp_path_info *info = data;
 	struct ipoib_dev_priv *priv;
 	struct net_device *dev = NULL;
 	struct rtable *rt;
@@ -376,11 +379,6 @@ static void do_link_path_lookup(void *da
 	 */
 	if (info->flags & SDP_LINK_F_PATH)
 		goto done;
-	/*
-	 * route information present, but no path query.
-	 */
-	if (info->ca)
-		goto path;
 
 	result = ip_route_output_key(&rt, &fl);
 	if (result < 0 || !rt) {
@@ -543,6 +541,13 @@ error:
 	ip_rt_put(rt);
 }
 
+static void retry_link_path_lookup(void *data)
+{
+	down(&sdp_link_mutex);
+	do_link_path_lookup(data);
+	up(&sdp_link_mutex);
+}
+
 /*
  * Public functions
  */
@@ -566,7 +571,9 @@ int sdp_link_path_lookup(u32 dst_addr,  
 {
 	struct sdp_path_info *info;
 	struct sdp_path_wait *wait;
-	int result;
+	int result = 0;
+
+	down(&sdp_link_mutex);
 
 	*id = _SDP_PATH_LOOKUP_ID();
 
@@ -589,7 +596,7 @@ int sdp_link_path_lookup(u32 dst_addr,  
 	 */
 	if (info->flags & SDP_LINK_F_VALID) {
 		sdp_link_path_complete(*id, 0, info, completion, arg);
-		return 0;
+		goto done;
 	}
 	/*
 	 * add request to list of lookups.
@@ -598,7 +605,7 @@ int sdp_link_path_lookup(u32 dst_addr,  
 	if (!wait) {
 		sdp_dbg_warn(NULL, "Failed to create path wait object");
 		result = -ENOMEM;
-		goto error;
+		goto done;
 	}
 
 	wait->id = *id;
@@ -613,8 +620,8 @@ int sdp_link_path_lookup(u32 dst_addr,  
 	if (!((SDP_LINK_F_ARP|SDP_LINK_F_PATH) & info->flags))
 		do_link_path_lookup(info);
 
-	return 0;
-error:
+done:
+	up(&sdp_link_mutex);
 	return result;
 }
 
@@ -630,6 +637,7 @@ static void sdp_link_sweep(void *data)
 	struct sdp_path_info *info;
 	struct sdp_path_info *sweep;
 
+	down(&sdp_link_mutex);
 	list_for_each_entry_safe(info, sweep, &info_list, info_list) {
 		if (jiffies > (info->use + SDP_LINK_INFO_TIMEOUT)) {
 			sdp_dbg_ctrl(NULL,
@@ -643,6 +651,7 @@ static void sdp_link_sweep(void *data)
 			sdp_path_info_destroy(info, -ETIMEDOUT);
 		}
 	}
+	up(&sdp_link_mutex);
 
 	queue_delayed_work(link_wq, &link_timer, SDP_LINK_SWEEP_INTERVAL);
 }
@@ -656,8 +665,8 @@ static void sdp_link_sweep(void *data)
  */
 static void sdp_link_arp_work(void *data)
 {
-	struct sdp_work *work = (struct sdp_work *)data;
-	struct sk_buff *skb = (struct sk_buff *)work->arg;
+	struct sdp_work *work = data;
+	struct sk_buff *skb = work->arg;
 	struct sdp_path_info *info;
 	struct sdp_link_arp *arp;
 	int result;
@@ -670,6 +679,8 @@ static void sdp_link_arp_work(void *data
 		     (arp->src_ip & 0x00ff0000) >> 16,
 		     (arp->src_ip & 0xff000000) >> 24,
 		     GID_ARG(arp->src_gid));
+
+	down(&sdp_link_mutex);
 	/*
 	 * find a path info structure for the source IP address.
 	 */
@@ -696,6 +707,7 @@ static void sdp_link_arp_work(void *data
 	}
 
 done:
+	up(&sdp_link_mutex);
 	kfree_skb(skb);
 	kfree(work);
 }
@@ -811,6 +823,7 @@ void sdp_link_addr_cleanup(void)
 	 * remove ARP packet processing.
 	 */
 	dev_remove_pack(&sdp_arp_type);
+	
 	/*
 	 * destroy work queue
 	 */

-- 
MST



More information about the general mailing list