[SSI] openssi/kernel/cluster/ssi/net ipvs_svr.c,1.27,1.28

Roger Tsang <[email protected]> Wed, 15 Dec 2010 08:01:53 +0000
Newsgroups gmane.linux.cluster.ssic.cvs
Message-ID <[email protected]>
Update of /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/net
In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv24416/kernel/cluster/ssi/net

Modified Files:
      Tag: OPENSSI-FC
	ipvs_svr.c 
Log Message:
cluster/ssi/net/ipvs_svr.c
- __get_director: new macro to increment value of ipvs_refcnt field in ipvs_dirinfo structure.
- put_director: use BUG_ON() macro instead of SSI_ASSERT(). when the condition is not met memory corruption may occur.
- inaddr_any_op: release ipvs_directors_sem before calling ipvs_add/del_entry() which can go remote. reduce contention with del_cvip() path.

cluster/ssi/net/ipvs_svr.c (#ifdef IPVS_REGISTER_PORTS_FIX)
- register_port: new function based on for-loop section in register_ports(). release ipvs_directors_sem before calling ipvs_add/del_entry() which can go remote. reduce contention with _del_cvip() path.
- register_ports: invoke register_port().


Index: ipvs_svr.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/net/ipvs_svr.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- ipvs_svr.c	17 Dec 2009 06:43:51 -0000	1.27
+++ ipvs_svr.c	15 Dec 2010 08:01:51 -0000	1.28
@@ -103,6 +103,8 @@
 	return info;
 }
 
+#define __get_director(info) atomic_inc(&info->ipvs_refcnt)
+
 struct ipvs_dirinfo *
 get_director(__u32 ip)
 {
@@ -112,7 +114,7 @@
 	list_for_each_entry(info, &ipvs_directors, list) {
 		if (info->daddr != ip)
 			continue;
-		atomic_inc(&info->ipvs_refcnt);
+		__get_director(info);
 		up_read(&ipvs_directors_sem);
 		return info;
 	}
@@ -142,7 +144,7 @@
 {
 	if (!atomic_dec_and_test(&info->ipvs_refcnt))
 		return;
-	SSI_ASSERT(list_empty(&info->list));
+	BUG_ON(!list_empty(&info->list));
 	__del_directors(info);
 	kfree(info);
 }
@@ -580,20 +582,32 @@
 	char *lvs_sched,
 	int is_addserv)
 {
-	struct ipvs_dirinfo *info;
+	struct ipvs_dirinfo *info, *tmp = NULL;
+
+	info = list_prepare_entry(tmp, &ipvs_directors, list);
 
 	down_read(&ipvs_directors_sem);
-	list_for_each_entry(info, &ipvs_directors, list) {
+	list_for_each_entry_continue(info, &ipvs_directors, list) {
 		if (!is_configured(info->daddr))
 			continue;
-		if (is_addserv)
+		__get_director(info);
+		up_read(&ipvs_directors_sem);
+
+		/* SSI_XXX: ignoring return value */
+		if (is_addserv) {
 			(void) ipvs_add_entry(info, port, rip, weight,
 							protocol, lvs_sched);
-		else
+		} else
 			(void) ipvs_del_entry(info, port, rip, protocol);
-		/* SSI_XXX: ignoring return value */
+
+		if (tmp)
+			put_director(tmp);
+		tmp = info;
+		down_read(&ipvs_directors_sem);
 	}
 	up_read(&ipvs_directors_sem);
+	if (tmp)
+		put_director(tmp);
 	return 0;
 }
 
@@ -1055,6 +1069,40 @@
 	return 0;
 }
 
+#ifdef IPVS_REGISTER_PORTS_FIX
+void
+register_port(
+	u_short port,
+	u_int rip,
+	int weight,
+	u_short protocol,
+	char *lvs_sched)
+{
+	struct ipvs_dirinfo *info, *tmp = NULL;
+
+	info = list_prepare_entry(tmp, &ipvs_directors, list);
+
+	down_read(&ipvs_directors_sem);
+	list_for_each_entry_continue(info, &ipvs_directors, list) {
+		if (!is_configured(info->daddr) ||
+		    !is_bound(port, protocol, info->daddr))
+			continue;
+		__get_director(info);
+		up_read(&ipvs_directors_sem);
+
+		(void) ipvs_add_entry(info, port, rip, weight,
+					protocol, lvs_sched);
+		if (tmp)
+			put_director(tmp);
+		tmp = info;
+		down_read(&ipvs_directors_sem);
+	}
+	up_read(&ipvs_directors_sem);
+	if (tmp)
+		put_director(tmp);
+}
+#endif /* IPVS_REGISTER_PORTS_FIX */
+
 /**
  * register_ports: Register the network services already listening to the director node
  */
@@ -1070,38 +1118,24 @@
 	icsinfo_t nodeinfo;
 	u_short port;
 #ifdef IPVS_REGISTER_PORTS_FIX
-	struct ipvs_dirinfo *info;
-
 	/* ICS interface  address is the real server address*/
 	if (ics_geticsinfo(this_node, &nodeinfo))
 		return;
-
 	rip = in_aton((char*)&nodeinfo);
-#endif
 
 	for (port = start_port; port <= end_port; port++) {
-#ifdef IPVS_REGISTER_PORTS_FIX
 		if (getport_desc(port, protocol, NULL))
 			continue;
-
 		if (!weight) {
 			/* Unregister port for ha-lvs unconfigure_services() */
 			(void) inaddr_any_op(htons(port), rip, weight, protocol,
 				      lvs_sched, 0);
-			continue;
-		}
-
-		down_read(&ipvs_directors_sem);
-		list_for_each_entry(info, &ipvs_directors, list) {
-			if (!is_configured(info->daddr) ||
-			    !is_bound(port, protocol, info->daddr))
-				continue;
-
-			(void) ipvs_add_entry(info, htons(port), rip, weight,
+		} else
+			register_port(htons(port), rip, weight,
 						protocol, lvs_sched);
-		}
-		up_read(&ipvs_directors_sem);
-#else
+	}
+#else /* IPVS_REGISTER_PORTS_FIX */
+	for (port = start_port; port <= end_port; port++) {
 		if (!is_bound(port, protocol))
 			continue;
 
@@ -1117,8 +1151,8 @@
 		 * registered with all the cvips
 		 */
 		(void) inaddr_any_op(htons(port), rip, weight, protocol, lvs_sched, 1);
-#endif
 	}
+#endif /* !IPVS_REGISTER_PORTS_FIX */
 }
 
 static int
@@ -1281,13 +1315,15 @@
 
 #ifdef IPVS_SERVICE_RACE_FIX
 	port = inet->sport;
+	/* NB: no race. update_ipvs_portweight_list() does not remove entries */
 	if (getport_desc(ntohs(port), protocol, NULL))
 		goto con_sock;
 
 	ret = del_ipvs_entry(cvip, port, rip, protocol);
 	if (ret) {
-		printk(KERN_ALERT "%s: delete IPVS real server %s:%d failed %d\n",
-				__FUNCTION__, (char *)&nodeinfo, port, ret);
+		printk(KERN_NOTICE "%s: delete IPVS real server %s:%d "
+			"failed %d\n", __FUNCTION__, (char *)&nodeinfo,
+			port, ret);
 	}
 #else
 	/* SSI_XXX: Not interested in the return value ?! */


------------------------------------------------------------------------------
Lotusphere 2011
Register now for Lotusphere 2011 and learn how
to connect the dots, take your collaborative environment
to the next level, and enter the era of Social Business.
http://p.sf.net/sfu/lotusphere-d2d