aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorJulian Anastasov <ja@ssi.bg>2013-03-21 05:58:09 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2013-04-01 18:23:44 -0400
commit60b6aa3b319d902db49dbaee7433fe2ac7d0cdb5 (patch)
tree6b41c22348ab58c270a3703605d98ba6c88327de /net/netfilter
parent276472eae063d717b775fdfc87529937402d0e08 (diff)
ipvs: convert locks used in persistence engines
Allow the readers to use RCU lock and for PE module registrations use global mutex instead of spinlock. All PE modules need to use synchronize_rcu in their module exit handler. Signed-off-by: Julian Anastasov <ja@ssi.bg> Signed-off by: Hans Schillstrom <hans@schillstrom.com> Signed-off-by: Simon Horman <horms@verge.net.au>
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/ipvs/ip_vs_pe.c43
-rw-r--r--net/netfilter/ipvs/ip_vs_pe_sip.c1
2 files changed, 14 insertions, 30 deletions
diff --git a/net/netfilter/ipvs/ip_vs_pe.c b/net/netfilter/ipvs/ip_vs_pe.c
index 5cf859ccb31b..5d9774c4cc4c 100644
--- a/net/netfilter/ipvs/ip_vs_pe.c
+++ b/net/netfilter/ipvs/ip_vs_pe.c
@@ -13,8 +13,8 @@
13/* IPVS pe list */ 13/* IPVS pe list */
14static LIST_HEAD(ip_vs_pe); 14static LIST_HEAD(ip_vs_pe);
15 15
16/* lock for service table */ 16/* semaphore for IPVS PEs. */
17static DEFINE_SPINLOCK(ip_vs_pe_lock); 17static DEFINE_MUTEX(ip_vs_pe_mutex);
18 18
19/* Bind a service with a pe */ 19/* Bind a service with a pe */
20void ip_vs_bind_pe(struct ip_vs_service *svc, struct ip_vs_pe *pe) 20void ip_vs_bind_pe(struct ip_vs_service *svc, struct ip_vs_pe *pe)
@@ -36,9 +36,8 @@ struct ip_vs_pe *__ip_vs_pe_getbyname(const char *pe_name)
36 IP_VS_DBG(10, "%s(): pe_name \"%s\"\n", __func__, 36 IP_VS_DBG(10, "%s(): pe_name \"%s\"\n", __func__,
37 pe_name); 37 pe_name);
38 38
39 spin_lock_bh(&ip_vs_pe_lock); 39 rcu_read_lock();
40 40 list_for_each_entry_rcu(pe, &ip_vs_pe, n_list) {
41 list_for_each_entry(pe, &ip_vs_pe, n_list) {
42 /* Test and get the modules atomically */ 41 /* Test and get the modules atomically */
43 if (pe->module && 42 if (pe->module &&
44 !try_module_get(pe->module)) { 43 !try_module_get(pe->module)) {
@@ -47,14 +46,14 @@ struct ip_vs_pe *__ip_vs_pe_getbyname(const char *pe_name)
47 } 46 }
48 if (strcmp(pe_name, pe->name)==0) { 47 if (strcmp(pe_name, pe->name)==0) {
49 /* HIT */ 48 /* HIT */
50 spin_unlock_bh(&ip_vs_pe_lock); 49 rcu_read_unlock();
51 return pe; 50 return pe;
52 } 51 }
53 if (pe->module) 52 if (pe->module)
54 module_put(pe->module); 53 module_put(pe->module);
55 } 54 }
55 rcu_read_unlock();
56 56
57 spin_unlock_bh(&ip_vs_pe_lock);
58 return NULL; 57 return NULL;
59} 58}
60 59
@@ -83,22 +82,13 @@ int register_ip_vs_pe(struct ip_vs_pe *pe)
83 /* increase the module use count */ 82 /* increase the module use count */
84 ip_vs_use_count_inc(); 83 ip_vs_use_count_inc();
85 84
86 spin_lock_bh(&ip_vs_pe_lock); 85 mutex_lock(&ip_vs_pe_mutex);
87
88 if (!list_empty(&pe->n_list)) {
89 spin_unlock_bh(&ip_vs_pe_lock);
90 ip_vs_use_count_dec();
91 pr_err("%s(): [%s] pe already linked\n",
92 __func__, pe->name);
93 return -EINVAL;
94 }
95
96 /* Make sure that the pe with this name doesn't exist 86 /* Make sure that the pe with this name doesn't exist
97 * in the pe list. 87 * in the pe list.
98 */ 88 */
99 list_for_each_entry(tmp, &ip_vs_pe, n_list) { 89 list_for_each_entry(tmp, &ip_vs_pe, n_list) {
100 if (strcmp(tmp->name, pe->name) == 0) { 90 if (strcmp(tmp->name, pe->name) == 0) {
101 spin_unlock_bh(&ip_vs_pe_lock); 91 mutex_unlock(&ip_vs_pe_mutex);
102 ip_vs_use_count_dec(); 92 ip_vs_use_count_dec();
103 pr_err("%s(): [%s] pe already existed " 93 pr_err("%s(): [%s] pe already existed "
104 "in the system\n", __func__, pe->name); 94 "in the system\n", __func__, pe->name);
@@ -106,8 +96,8 @@ int register_ip_vs_pe(struct ip_vs_pe *pe)
106 } 96 }
107 } 97 }
108 /* Add it into the d-linked pe list */ 98 /* Add it into the d-linked pe list */
109 list_add(&pe->n_list, &ip_vs_pe); 99 list_add_rcu(&pe->n_list, &ip_vs_pe);
110 spin_unlock_bh(&ip_vs_pe_lock); 100 mutex_unlock(&ip_vs_pe_mutex);
111 101
112 pr_info("[%s] pe registered.\n", pe->name); 102 pr_info("[%s] pe registered.\n", pe->name);
113 103
@@ -118,17 +108,10 @@ EXPORT_SYMBOL_GPL(register_ip_vs_pe);
118/* Unregister a pe from the pe list */ 108/* Unregister a pe from the pe list */
119int unregister_ip_vs_pe(struct ip_vs_pe *pe) 109int unregister_ip_vs_pe(struct ip_vs_pe *pe)
120{ 110{
121 spin_lock_bh(&ip_vs_pe_lock); 111 mutex_lock(&ip_vs_pe_mutex);
122 if (list_empty(&pe->n_list)) {
123 spin_unlock_bh(&ip_vs_pe_lock);
124 pr_err("%s(): [%s] pe is not in the list. failed\n",
125 __func__, pe->name);
126 return -EINVAL;
127 }
128
129 /* Remove it from the d-linked pe list */ 112 /* Remove it from the d-linked pe list */
130 list_del(&pe->n_list); 113 list_del_rcu(&pe->n_list);
131 spin_unlock_bh(&ip_vs_pe_lock); 114 mutex_unlock(&ip_vs_pe_mutex);
132 115
133 /* decrease the module use count */ 116 /* decrease the module use count */
134 ip_vs_use_count_dec(); 117 ip_vs_use_count_dec();
diff --git a/net/netfilter/ipvs/ip_vs_pe_sip.c b/net/netfilter/ipvs/ip_vs_pe_sip.c
index 12475ef88daf..00cc0241ed87 100644
--- a/net/netfilter/ipvs/ip_vs_pe_sip.c
+++ b/net/netfilter/ipvs/ip_vs_pe_sip.c
@@ -172,6 +172,7 @@ static int __init ip_vs_sip_init(void)
172static void __exit ip_vs_sip_cleanup(void) 172static void __exit ip_vs_sip_cleanup(void)
173{ 173{
174 unregister_ip_vs_pe(&ip_vs_sip_pe); 174 unregister_ip_vs_pe(&ip_vs_sip_pe);
175 synchronize_rcu();
175} 176}
176 177
177module_init(ip_vs_sip_init); 178module_init(ip_vs_sip_init);