[SSI] openssi/kernel/cluster/ssi/net ipvs_svr.c,1.28,1.29
Roger Tsang <[email protected]> Wed, 18 Dec 2013 07:10:33 +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-serv7714/cluster/ssi/net
Modified Files:
Tag: OPENSSI-FC
ipvs_svr.c
Log Message:
- ssi_inet_bind, ssi_inet_listen: remove extra inet_release() in error path.
- ssi_inet_bind, ssi_inet_listen, ssi_inet_release: fix debug messages printing IP port number in network byte order.
- implement lockless ipvs_directors list traversal.
Index: ipvs_svr.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/net/ipvs_svr.c,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- ipvs_svr.c 15 Dec 2010 08:01:51 -0000 1.28
+++ ipvs_svr.c 18 Dec 2013 07:10:31 -0000 1.29
@@ -57,7 +57,7 @@
extern int ipvs_del_entry(struct ipvs_dirinfo *, u_short, u_int, u_short);
static LIST_HEAD(ipvs_directors);
-static DECLARE_RWSEM(ipvs_directors_sem);
+static DEFINE_SPINLOCK(ipvs_directors_lock);
static LIST_HEAD(h_tcppwlist);
static LIST_HEAD(h_udppwlist);
@@ -95,32 +95,32 @@
info->daddr = ip;
info->p_directornode = NULL;
spin_lock_init(&info->ipvs_lock);
+ INIT_RCU_HEAD(&info->ipvs_rcu);
- down_write(&ipvs_directors_sem);
- list_add(&info->list, &ipvs_directors);
- up_write(&ipvs_directors_sem);
+ spin_lock(&ipvs_directors_lock);
+ list_add_rcu(&info->list, &ipvs_directors);
+ spin_unlock(&ipvs_directors_lock);
return info;
}
-#define __get_director(info) atomic_inc(&info->ipvs_refcnt)
+#define __get_director(info) atomic_test_and_add(1, &info->ipvs_refcnt)
struct ipvs_dirinfo *
get_director(__u32 ip)
{
struct ipvs_dirinfo *info;
- down_read(&ipvs_directors_sem);
- list_for_each_entry(info, &ipvs_directors, list) {
- if (info->daddr != ip)
- continue;
- __get_director(info);
- up_read(&ipvs_directors_sem);
- return info;
+ rcu_read_lock();
+ list_for_each_entry_rcu(info, &ipvs_directors, list) {
+ if (info->daddr == ip &&
+ __get_director(info))
+ goto found;
}
- up_read(&ipvs_directors_sem);
-
- return NULL;
+ info = NULL;
+found:
+ rcu_read_unlock();
+ return info;
}
/*
@@ -140,13 +140,23 @@
}
static void
+ipvs_dirinfo_rcu_free(struct rcu_head *head)
+{
+ struct ipvs_dirinfo *info =
+ container_of(head, struct ipvs_dirinfo, ipvs_rcu);
+ kfree(info);
+}
+
+static void
put_director(struct ipvs_dirinfo *info)
{
- if (!atomic_dec_and_test(&info->ipvs_refcnt))
+ if (!atomic_dec_and_lock(&info->ipvs_refcnt, &ipvs_directors_lock))
return;
- BUG_ON(!list_empty(&info->list));
+ list_del_rcu(&info->list);
+ spin_unlock(&ipvs_directors_lock);
+
__del_directors(info);
- kfree(info);
+ call_rcu(&info->ipvs_rcu, &ipvs_dirinfo_rcu_free);
}
static inline void
@@ -157,9 +167,6 @@
info = get_director(ip);
if (!info)
return;
- down_write(&ipvs_directors_sem);
- list_del_init(&(info->list));
- up_write(&ipvs_directors_sem);
put_director(info);
put_director(info); /* active */
}
@@ -449,13 +456,13 @@
seq_printf(m, "CVIP Address \tNode number\n");
- down_read(&ipvs_directors_sem);
- list_for_each_entry(info, &ipvs_directors, list) {
+ rcu_read_lock();
+ list_for_each_entry_rcu(info, &ipvs_directors, list) {
char tbuf[16];
sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(info->daddr));
seq_printf(m, "%-16s\t%u\n", tbuf, info->dnode);
}
- up_read(&ipvs_directors_sem);
+ rcu_read_unlock();
return 0;
}
@@ -582,16 +589,19 @@
char *lvs_sched,
int is_addserv)
{
- struct ipvs_dirinfo *info, *tmp = NULL;
+ struct ipvs_dirinfo *info;
+ struct list_head *pos = &ipvs_directors;
- info = list_prepare_entry(tmp, &ipvs_directors, list);
+ rcu_read_lock();
+ list_for_each_continue_rcu(pos, &ipvs_directors) {
+ info = list_entry(pos, typeof(*info), list);
+ if (!__get_director(info))
+ continue;
+ rcu_read_unlock();
- down_read(&ipvs_directors_sem);
- list_for_each_entry_continue(info, &ipvs_directors, list) {
+ might_sleep();
if (!is_configured(info->daddr))
- continue;
- __get_director(info);
- up_read(&ipvs_directors_sem);
+ goto next;
/* SSI_XXX: ignoring return value */
if (is_addserv) {
@@ -599,15 +609,11 @@
protocol, lvs_sched);
} else
(void) ipvs_del_entry(info, port, rip, protocol);
-
- if (tmp)
- put_director(tmp);
- tmp = info;
- down_read(&ipvs_directors_sem);
+next:
+ rcu_read_lock();
+ put_director(info);
}
- up_read(&ipvs_directors_sem);
- if (tmp)
- put_director(tmp);
+ rcu_read_unlock();
return 0;
}
@@ -1078,28 +1084,28 @@
u_short protocol,
char *lvs_sched)
{
- struct ipvs_dirinfo *info, *tmp = NULL;
+ struct ipvs_dirinfo *info;
+ struct list_head *pos = &ipvs_directors;
- info = list_prepare_entry(tmp, &ipvs_directors, list);
+ rcu_read_lock();
+ list_for_each_continue_rcu(pos, &ipvs_directors) {
+ info = list_entry(pos, typeof(*info), list);
+ if (!__get_director(info))
+ continue;
+ rcu_read_unlock();
- down_read(&ipvs_directors_sem);
- list_for_each_entry_continue(info, &ipvs_directors, list) {
+ might_sleep();
if (!is_configured(info->daddr) ||
!is_bound(port, protocol, info->daddr))
- continue;
- __get_director(info);
- up_read(&ipvs_directors_sem);
+ goto next;
(void) ipvs_add_entry(info, port, rip, weight,
protocol, lvs_sched);
- if (tmp)
- put_director(tmp);
- tmp = info;
- down_read(&ipvs_directors_sem);
+next:
+ rcu_read_lock();
+ put_director(info);
}
- up_read(&ipvs_directors_sem);
- if (tmp)
- put_director(tmp);
+ rcu_read_unlock();
}
#endif /* IPVS_REGISTER_PORTS_FIX */
@@ -1166,7 +1172,7 @@
u_int32_t cvip; /* IPv4 cluster virutal IP */
u_int32_t rip; /* real server IP */
icsinfo_t nodeinfo;
- int ret;
+ int ret, err;
/* ICS interface address is the real server address*/
if (ics_geticsinfo(this_node, &nodeinfo))
@@ -1175,25 +1181,18 @@
rip = in_aton((char*)&nodeinfo);
cvip = inet->rcv_saddr;
-#ifdef IPVS_SERVICE_RACE_FIX
- if ((ret = inet_listen(sock, backlog)))
- return ret;
-#endif
-
ret = register_ipvs_service(cvip, inet->sport, rip, protocol);
if (ret) {
/*
* Failed to register the service
*/
#ifdef IPVS_SERVICE_RACE_FIX
- (void) inet_release(sock);
printk(KERN_ALERT "%s: register IPVS real server %s:%d failed %d\n",
- __FUNCTION__, (char *)&nodeinfo, inet->sport, ret);
+ __FUNCTION__, (char *)&nodeinfo, ntohs(inet->sport), ret);
#endif
return ret;
}
-#ifndef IPVS_SERVICE_RACE_FIX
/*
* Do the actual listen
*/
@@ -1202,9 +1201,12 @@
/*
* IF listen fails delete the service and come out
*/
- del_ipvs_entry(cvip, inet->sport, rip, protocol);
+ err = del_ipvs_entry(cvip, inet->sport, rip, protocol);
+ if (err)
+ printk(KERN_NOTICE "%s: delete IPVS real server %s:%d "
+ "failed %d\n", __FUNCTION__, (char *)&nodeinfo,
+ ntohs(inet->sport), err);
}
-#endif
return ret;
}
@@ -1228,7 +1230,7 @@
u_int32_t cvip; /* IPv4 cluster virutal IP */
u_int32_t rip; /* real server IP */
icsinfo_t nodeinfo;
- int ret;
+ int ret, err;
/* ICS interface address is the real server address*/
if (ics_geticsinfo(this_node, &nodeinfo))
@@ -1237,25 +1239,18 @@
rip = in_aton((char*)&nodeinfo);
cvip = addr->sin_addr.s_addr;
-#ifdef IPVS_SERVICE_RACE_FIX
- if ((ret = inet_bind(sock, uaddr, addr_len)))
- return ret;
-#endif
-
ret = register_ipvs_service(cvip, addr->sin_port, rip, protocol);
if (ret) {
/*
* Failed to register the service
*/
#ifdef IPVS_SERVICE_RACE_FIX
- (void) inet_release(sock);
printk(KERN_ALERT "%s: register IPVS real server %s:%d failed %d\n",
- __FUNCTION__, (char *)&nodeinfo, addr->sin_port, ret);
+ __FUNCTION__, (char *)&nodeinfo, ntohs(addr->sin_port), ret);
#endif
return ret;
}
-#ifndef IPVS_SERVICE_RACE_FIX
/*
* Do the actual bind
*/
@@ -1264,9 +1259,12 @@
/*
* IF bind fails delete the service and come out
*/
- del_ipvs_entry(cvip, addr->sin_port, rip, protocol);
+ err = del_ipvs_entry(cvip, addr->sin_port, rip, protocol);
+ if (err)
+ printk(KERN_NOTICE "%s: delete IPVS real server %s:%d "
+ "failed %d\n", __FUNCTION__, (char *)&nodeinfo,
+ ntohs(addr->sin_port), err);
}
-#endif
return ret;
}
@@ -1323,7 +1321,7 @@
if (ret) {
printk(KERN_NOTICE "%s: delete IPVS real server %s:%d "
"failed %d\n", __FUNCTION__, (char *)&nodeinfo,
- port, ret);
+ ntohs(port), ret);
}
#else
/* SSI_XXX: Not interested in the return value ?! */
------------------------------------------------------------------------------
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