[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