[SSI] openssi/kernel/cluster/ssi/net ipvs_svr.c,1.30,1.31

Roger Tsang <[email protected]> Wed, 18 Dec 2013 07:55:48 +0000
Newsgroups gmane.linux.cluster.ssic.cvs
Message-ID <[email protected]>
Update of /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/net
In directory sfp-cvs-1.v30.ch3.sourceforge.com:/tmp/cvs-serv10327/cluster/ssi/net

Modified Files:
      Tag: OPENSSI-FC
	ipvs_svr.c 
Log Message:
- inaddr_any_op: use list_for_each_entry_rcu() primitive instead of list_for_each_continue_rcu().
- put_director: optimize away __del_directors() since the final put_director() cannot race.
- register_ipvs_service: fix Aneesh's code comment.
- register_ports: use list_for_each_entry_rcu() primitive instead of list_for_each_continue_rcu(). (#ifdef IPVS_REGISTER_PORTS_FIX)
- register_ports: caller ensures we can optimize away getport_desc() test. (#ifdef IPVS_REGISTER_PORTS_FIX)
- register_ports: fix regression. passing byte-swapped port number broke is_bound() test in register_port() code path. fixes `setport_weight` userland did not register into IPVS cluster already running services (existing listen ports) until the next time the affected services are restarted. (#ifdef IPVS_REGISTER_PORTS_FIX)
- set_pos_director: fix regression struct ipvs_dirinfo reference count leak. bug introduced in CVS tag OPENSSI-FC-1-9-6-PRE2


Index: ipvs_svr.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/net/ipvs_svr.c,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -d -r1.30 -r1.31
--- ipvs_svr.c	18 Dec 2013 07:32:38 -0000	1.30
+++ ipvs_svr.c	18 Dec 2013 07:55:46 -0000	1.31
@@ -154,8 +154,8 @@
 		return;
 	list_del_rcu(&info->list);
 	spin_unlock(&ipvs_directors_lock);
-
-	__del_directors(info);
+	if (info->p_directornode)
+		kfree(info->p_directornode);
 	call_rcu(&info->ipvs_rcu, &ipvs_dirinfo_rcu_free);
 }
 
@@ -274,7 +274,6 @@
 	char *sched,
 	int sched_len)
 {
-	struct ipvs_dirinfo *info;
 	char lvs_sched[IP_VS_SCHEDNAME_MAXLEN];
 
 	sched_len = min(sched_len, IP_VS_SCHEDNAME_MAXLEN-1);
@@ -282,34 +281,23 @@
 	lvs_sched[sched_len] = '\0';
 
 	*rval = service_add(cvip, port, rip, weight, protocol, lvs_sched);
-
-	/* Inform all the possible director nodes */
-	if ((!*rval || *rval == -EEXIST) && (info = get_director(cvip))) {
-		if (__is_master_director(info))
-			(void) pdirector_update(info, port, rip, weight,
-						protocol, lvs_sched, 1);
-		put_director(info);
-	}
-
 	return 0;
 }
 
-void
-local_ipvs_add_entry(
+int
+ipvs_add_entry(
 	struct ipvs_dirinfo *info,
-	int *rval,
 	u_short port,
 	u_int rip,
 	int weight,
 	u_short protocol,
 	char *sched)
 {
-	SSI_ASSERT(__is_master_director(info));
-	*rval = service_add(info->daddr, port, rip, weight, protocol, sched);
-
-	/* Inform all the possible director nodes */
-	if (!*rval || *rval == -EEXIST)
+	int rval = service_add(info->daddr, port, rip, weight, protocol, sched);
+	if (!rval)
+		/* Inform all the possible director nodes */
 		(void) pdirector_update(info, port, rip, weight, protocol, sched, 1);
+	return rval;
 }
 
 int
@@ -321,34 +309,22 @@
 	u_int rip,
 	u_short protocol)
 {
-	struct ipvs_dirinfo *info;
-
 	*rval = service_del(cvip, port, rip, protocol);
-
-	/* Inform all the possible director nodes */
-	if ((*rval != -EBADR) && (info = get_director(cvip))) {
-		if (__is_master_director(info))
-			(void) pdirector_update(info, port, rip, 0, protocol, 0, 0);
-		put_director(info);
-	}
-
 	return 0;
 }
 
-void
-local_ipvs_del_entry(
+int
+ipvs_del_entry(
 	struct ipvs_dirinfo *info,
-	int *rval,
 	u_short port,
 	u_int rip,
 	u_short protocol)
 {
-	SSI_ASSERT(__is_master_director(info));
-	*rval = service_del(info->daddr, port, rip, protocol);
-
-	/* Inform all the possible director nodes */
-	if (*rval != -EBADR)
+	int rval = service_del(info->daddr, port, rip, protocol);
+	if (rval != -EBADR)
+		/* Inform all the possible director nodes */
 		(void) pdirector_update(info, port, rip, 0, protocol, 0, 0);
+	return rval;
 }
 
 
@@ -551,11 +527,9 @@
 	int is_addserv)
 {
 	struct ipvs_dirinfo *info;
-	struct list_head *pos = &ipvs_directors;
 
 	rcu_read_lock();
-	list_for_each_continue_rcu(pos, &ipvs_directors) {
-		info = list_entry(pos, typeof(*info), list);
+	list_for_each_entry_rcu(info, &ipvs_directors, list) {
 		if (!__get_director(info))
 			continue;
 		rcu_read_unlock();
@@ -604,19 +578,19 @@
 		} else if (port >= tplist->start_port) {
 #ifndef IPVS_SERVICE_RACE_FIX
 			up_read(&pwlist_sem);
-#else
-			if (!pdesc) {
-				up_read(&pwlist_sem);
-				return 0;
-			}
-#endif
 			pdesc->weight = tplist->weight;
 			strlcpy(pdesc->lvs_sched, tplist->lvs_sched, IP_VS_SCHEDNAME_MAXLEN);
-#ifdef IPVS_SERVICE_RACE_FIX
-			up_read(&pwlist_sem);
-#endif
 			pdesc->port   = port;
 			return 0;
+#else
+			if (pdesc) {
+				pdesc->port   = port;
+				pdesc->weight = tplist->weight;
+				strlcpy(pdesc->lvs_sched, tplist->lvs_sched, IP_VS_SCHEDNAME_MAXLEN);
+			}
+			up_read(&pwlist_sem);
+			return 0;
+#endif
 		}
 		break;
 	}
@@ -636,19 +610,11 @@
 	int ret;
 
 	if (getport_desc(ntohs(port), protocol, &pdesc)) {
-		/*
-		 * if weight returned is 0 that means  the port
-		 * is not registered for load  balancing
-		 */
+		/* port is not registered for load balancing */
 		return 0;
 	}
-
-	if (pdesc.weight == 0) {
-		/*
-		 *  Weight was reset to zero
-		 */
+	if (pdesc.weight == 0)
 		return 0;
-	}
 
 	if (bindip == INADDR_ANY)
 		return inaddr_any_op(port, rip, pdesc.weight,
@@ -900,8 +866,10 @@
 	if (!info->p_directornode) {
 		spin_unlock(&info->ipvs_lock);
 		dirnodes = kzmalloc(MAX_DIRECTORS * sizeof(*dirnodes), GFP_KERNEL);
-		if (!dirnodes)
+		if (!dirnodes) {
+			put_director(info);
 			return -ENOMEM;
+		}
 
 		spin_lock(&info->ipvs_lock);
 		if (info->p_directornode) /* lost race */
@@ -921,6 +889,7 @@
 		}
 	}
 	spin_unlock(&info->ipvs_lock);
+	put_director(info);
 
 	/* Cannot add more than MAX_DIRECTORS */
 	if (i == MAX_DIRECTORS)
@@ -935,18 +904,15 @@
 	struct ipvs_dirinfo *info;
 
 	/* Allow this to run only on cvip master director node */
-	if ((info = get_director(dipaddr))) {
-		if (__is_master_director(info)) {
-			put_director(info);
-			/* TODO: Could optimize away get_director() in path:
-			 * set_master_director, ripvs_setdirector, modify_director,
-			 * get_director.
-			 */
-			return set_master_director(dipaddr, CLUSTERNODE_INVAL);
-		}
+	if (!(info = get_director(dipaddr)))
+		return -EINVAL;
+	if (!__is_master_director(info)) {
 		put_director(info);
+		return -EINVAL;
 	}
-	return -EINVAL;
+	put_director(info);
+
+	return set_master_director(dipaddr, CLUSTERNODE_INVAL);
 }
 
 #ifdef IPVS_REGISTER_PORTS_FIX
@@ -1014,13 +980,12 @@
 		local_bh_enable();
 	} else {
 		/* UDP */
-		struct hlist_head *uhash;
 		struct hlist_node *node;
 		struct sock *sk2;
 
 		read_lock_bh(&udp_hash_lock);
-		uhash = &udp_hash[port & (UDP_HTABLE_SIZE - 1)];
-		sk_for_each(sk2, node, uhash) {
+		sk_for_each(sk2, node,
+			    &udp_hash[port & (UDP_HTABLE_SIZE - 1)]) {
 			struct inet_sock *inet2 = inet_sk(sk2);
 #ifdef IPVS_REGISTER_PORTS_FIX
 			if (inet2->num == port && inet2->rcv_saddr == cvip) {
@@ -1046,11 +1011,9 @@
 	char *lvs_sched)
 {
 	struct ipvs_dirinfo *info;
-	struct list_head *pos = &ipvs_directors;
 
 	rcu_read_lock();
-	list_for_each_continue_rcu(pos, &ipvs_directors) {
-		info = list_entry(pos, typeof(*info), list);
+	list_for_each_entry_rcu(info, &ipvs_directors, list) {
 		if (!__get_director(info))
 			continue;
 		rcu_read_unlock();
@@ -1060,7 +1023,7 @@
 		    !is_bound(port, protocol, info->daddr))
 			goto next;
 
-		(void) ipvs_add_entry(info, port, rip, weight,
+		(void) ipvs_add_entry(info, htons(port), rip, weight,
 					protocol, lvs_sched);
 next:
 		rcu_read_lock();
@@ -1091,15 +1054,13 @@
 	rip = in_aton((char*)&nodeinfo);
 
 	for (port = start_port; port <= end_port; port++) {
-		if (getport_desc(port, protocol, NULL))
-			continue;
-		if (!weight) {
+		if (unlikely(!weight)) {
 			/* Unregister port for ha-lvs unconfigure_services() */
 			(void) inaddr_any_op(htons(port), rip, weight, protocol,
 				      lvs_sched, 0);
-		} else
-			register_port(htons(port), rip, weight,
-						protocol, lvs_sched);
+			continue;
+		}
+		register_port(port, rip, weight, protocol, lvs_sched);
 	}
 #else /* IPVS_REGISTER_PORTS_FIX */
 	for (port = start_port; port <= end_port; port++) {


------------------------------------------------------------------------------
Rapidly troubleshoot problems before they affect your business. Most IT 
organizations don't have a clear picture of how application performance 
affects their revenue. With AppDynamics, you get 100% visibility into your 
Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk