Commit 60b6aa3b authored by Julian Anastasov's avatar Julian Anastasov Committed by Pablo Neira Ayuso

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: default avatarJulian Anastasov <ja@ssi.bg>
Signed-off by: Hans Schillstrom <hans@schillstrom.com>
Signed-off-by: default avatarSimon Horman <horms@verge.net.au>
parent 276472ea
...@@ -13,8 +13,8 @@ ...@@ -13,8 +13,8 @@
/* IPVS pe list */ /* IPVS pe list */
static LIST_HEAD(ip_vs_pe); static LIST_HEAD(ip_vs_pe);
/* lock for service table */ /* semaphore for IPVS PEs. */
static DEFINE_SPINLOCK(ip_vs_pe_lock); static DEFINE_MUTEX(ip_vs_pe_mutex);
/* Bind a service with a pe */ /* Bind a service with a pe */
void ip_vs_bind_pe(struct ip_vs_service *svc, struct ip_vs_pe *pe) void 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,9 +36,8 @@ struct ip_vs_pe *__ip_vs_pe_getbyname(const char *pe_name)
IP_VS_DBG(10, "%s(): pe_name \"%s\"\n", __func__, IP_VS_DBG(10, "%s(): pe_name \"%s\"\n", __func__,
pe_name); pe_name);
spin_lock_bh(&ip_vs_pe_lock); rcu_read_lock();
list_for_each_entry_rcu(pe, &ip_vs_pe, n_list) {
list_for_each_entry(pe, &ip_vs_pe, n_list) {
/* Test and get the modules atomically */ /* Test and get the modules atomically */
if (pe->module && if (pe->module &&
!try_module_get(pe->module)) { !try_module_get(pe->module)) {
...@@ -47,14 +46,14 @@ struct ip_vs_pe *__ip_vs_pe_getbyname(const char *pe_name) ...@@ -47,14 +46,14 @@ struct ip_vs_pe *__ip_vs_pe_getbyname(const char *pe_name)
} }
if (strcmp(pe_name, pe->name)==0) { if (strcmp(pe_name, pe->name)==0) {
/* HIT */ /* HIT */
spin_unlock_bh(&ip_vs_pe_lock); rcu_read_unlock();
return pe; return pe;
} }
if (pe->module) if (pe->module)
module_put(pe->module); module_put(pe->module);
} }
rcu_read_unlock();
spin_unlock_bh(&ip_vs_pe_lock);
return NULL; return NULL;
} }
...@@ -83,22 +82,13 @@ int register_ip_vs_pe(struct ip_vs_pe *pe) ...@@ -83,22 +82,13 @@ int register_ip_vs_pe(struct ip_vs_pe *pe)
/* increase the module use count */ /* increase the module use count */
ip_vs_use_count_inc(); ip_vs_use_count_inc();
spin_lock_bh(&ip_vs_pe_lock); mutex_lock(&ip_vs_pe_mutex);
if (!list_empty(&pe->n_list)) {
spin_unlock_bh(&ip_vs_pe_lock);
ip_vs_use_count_dec();
pr_err("%s(): [%s] pe already linked\n",
__func__, pe->name);
return -EINVAL;
}
/* Make sure that the pe with this name doesn't exist /* Make sure that the pe with this name doesn't exist
* in the pe list. * in the pe list.
*/ */
list_for_each_entry(tmp, &ip_vs_pe, n_list) { list_for_each_entry(tmp, &ip_vs_pe, n_list) {
if (strcmp(tmp->name, pe->name) == 0) { if (strcmp(tmp->name, pe->name) == 0) {
spin_unlock_bh(&ip_vs_pe_lock); mutex_unlock(&ip_vs_pe_mutex);
ip_vs_use_count_dec(); ip_vs_use_count_dec();
pr_err("%s(): [%s] pe already existed " pr_err("%s(): [%s] pe already existed "
"in the system\n", __func__, pe->name); "in the system\n", __func__, pe->name);
...@@ -106,8 +96,8 @@ int register_ip_vs_pe(struct ip_vs_pe *pe) ...@@ -106,8 +96,8 @@ int register_ip_vs_pe(struct ip_vs_pe *pe)
} }
} }
/* Add it into the d-linked pe list */ /* Add it into the d-linked pe list */
list_add(&pe->n_list, &ip_vs_pe); list_add_rcu(&pe->n_list, &ip_vs_pe);
spin_unlock_bh(&ip_vs_pe_lock); mutex_unlock(&ip_vs_pe_mutex);
pr_info("[%s] pe registered.\n", pe->name); pr_info("[%s] pe registered.\n", pe->name);
...@@ -118,17 +108,10 @@ EXPORT_SYMBOL_GPL(register_ip_vs_pe); ...@@ -118,17 +108,10 @@ EXPORT_SYMBOL_GPL(register_ip_vs_pe);
/* Unregister a pe from the pe list */ /* Unregister a pe from the pe list */
int unregister_ip_vs_pe(struct ip_vs_pe *pe) int unregister_ip_vs_pe(struct ip_vs_pe *pe)
{ {
spin_lock_bh(&ip_vs_pe_lock); mutex_lock(&ip_vs_pe_mutex);
if (list_empty(&pe->n_list)) {
spin_unlock_bh(&ip_vs_pe_lock);
pr_err("%s(): [%s] pe is not in the list. failed\n",
__func__, pe->name);
return -EINVAL;
}
/* Remove it from the d-linked pe list */ /* Remove it from the d-linked pe list */
list_del(&pe->n_list); list_del_rcu(&pe->n_list);
spin_unlock_bh(&ip_vs_pe_lock); mutex_unlock(&ip_vs_pe_mutex);
/* decrease the module use count */ /* decrease the module use count */
ip_vs_use_count_dec(); ip_vs_use_count_dec();
......
...@@ -172,6 +172,7 @@ static int __init ip_vs_sip_init(void) ...@@ -172,6 +172,7 @@ static int __init ip_vs_sip_init(void)
static void __exit ip_vs_sip_cleanup(void) static void __exit ip_vs_sip_cleanup(void)
{ {
unregister_ip_vs_pe(&ip_vs_sip_pe); unregister_ip_vs_pe(&ip_vs_sip_pe);
synchronize_rcu();
} }
module_init(ip_vs_sip_init); module_init(ip_vs_sip_init);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment