Commit 44f4d5a2 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont Committed by David S. Miller

Phonet: convert bound sockets hash list to RCU

This gets rid of the last spinlock in the Phonet stack proper.
Signed-off-by: default avatarRémi Denis-Courmont <remi.denis-courmont@nokia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fce55922
...@@ -52,7 +52,7 @@ static int pn_socket_release(struct socket *sock) ...@@ -52,7 +52,7 @@ static int pn_socket_release(struct socket *sock)
static struct { static struct {
struct hlist_head hlist[PN_HASHSIZE]; struct hlist_head hlist[PN_HASHSIZE];
spinlock_t lock; struct mutex lock;
} pnsocks; } pnsocks;
void __init pn_sock_init(void) void __init pn_sock_init(void)
...@@ -61,7 +61,7 @@ void __init pn_sock_init(void) ...@@ -61,7 +61,7 @@ void __init pn_sock_init(void)
for (i = 0; i < PN_HASHSIZE; i++) for (i = 0; i < PN_HASHSIZE; i++)
INIT_HLIST_HEAD(pnsocks.hlist + i); INIT_HLIST_HEAD(pnsocks.hlist + i);
spin_lock_init(&pnsocks.lock); mutex_init(&pnsocks.lock);
} }
static struct hlist_head *pn_hash_list(u16 obj) static struct hlist_head *pn_hash_list(u16 obj)
...@@ -82,9 +82,8 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn) ...@@ -82,9 +82,8 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn)
u8 res = spn->spn_resource; u8 res = spn->spn_resource;
struct hlist_head *hlist = pn_hash_list(obj); struct hlist_head *hlist = pn_hash_list(obj);
spin_lock_bh(&pnsocks.lock); rcu_read_lock();
sk_for_each_rcu(sknode, node, hlist) {
sk_for_each(sknode, node, hlist) {
struct pn_sock *pn = pn_sk(sknode); struct pn_sock *pn = pn_sk(sknode);
BUG_ON(!pn->sobject); /* unbound socket */ BUG_ON(!pn->sobject); /* unbound socket */
...@@ -107,8 +106,7 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn) ...@@ -107,8 +106,7 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn)
sock_hold(sknode); sock_hold(sknode);
break; break;
} }
rcu_read_unlock();
spin_unlock_bh(&pnsocks.lock);
return rval; return rval;
} }
...@@ -119,7 +117,7 @@ void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb) ...@@ -119,7 +117,7 @@ void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb)
struct hlist_head *hlist = pnsocks.hlist; struct hlist_head *hlist = pnsocks.hlist;
unsigned h; unsigned h;
spin_lock(&pnsocks.lock); rcu_read_lock();
for (h = 0; h < PN_HASHSIZE; h++) { for (h = 0; h < PN_HASHSIZE; h++) {
struct hlist_node *node; struct hlist_node *node;
struct sock *sknode; struct sock *sknode;
...@@ -140,25 +138,26 @@ void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb) ...@@ -140,25 +138,26 @@ void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb)
} }
hlist++; hlist++;
} }
spin_unlock(&pnsocks.lock); rcu_read_unlock();
} }
void pn_sock_hash(struct sock *sk) void pn_sock_hash(struct sock *sk)
{ {
struct hlist_head *hlist = pn_hash_list(pn_sk(sk)->sobject); struct hlist_head *hlist = pn_hash_list(pn_sk(sk)->sobject);
spin_lock_bh(&pnsocks.lock); mutex_lock(&pnsocks.lock);
sk_add_node(sk, hlist); sk_add_node_rcu(sk, hlist);
spin_unlock_bh(&pnsocks.lock); mutex_unlock(&pnsocks.lock);
} }
EXPORT_SYMBOL(pn_sock_hash); EXPORT_SYMBOL(pn_sock_hash);
void pn_sock_unhash(struct sock *sk) void pn_sock_unhash(struct sock *sk)
{ {
spin_lock_bh(&pnsocks.lock); mutex_lock(&pnsocks.lock);
sk_del_node_init(sk); sk_del_node_init_rcu(sk);
spin_unlock_bh(&pnsocks.lock); mutex_unlock(&pnsocks.lock);
pn_sock_unbind_all_res(sk); pn_sock_unbind_all_res(sk);
synchronize_rcu();
} }
EXPORT_SYMBOL(pn_sock_unhash); EXPORT_SYMBOL(pn_sock_unhash);
...@@ -548,7 +547,7 @@ static struct sock *pn_sock_get_idx(struct seq_file *seq, loff_t pos) ...@@ -548,7 +547,7 @@ static struct sock *pn_sock_get_idx(struct seq_file *seq, loff_t pos)
unsigned h; unsigned h;
for (h = 0; h < PN_HASHSIZE; h++) { for (h = 0; h < PN_HASHSIZE; h++) {
sk_for_each(sknode, node, hlist) { sk_for_each_rcu(sknode, node, hlist) {
if (!net_eq(net, sock_net(sknode))) if (!net_eq(net, sock_net(sknode)))
continue; continue;
if (!pos) if (!pos)
...@@ -572,9 +571,9 @@ static struct sock *pn_sock_get_next(struct seq_file *seq, struct sock *sk) ...@@ -572,9 +571,9 @@ static struct sock *pn_sock_get_next(struct seq_file *seq, struct sock *sk)
} }
static void *pn_sock_seq_start(struct seq_file *seq, loff_t *pos) static void *pn_sock_seq_start(struct seq_file *seq, loff_t *pos)
__acquires(pnsocks.lock) __acquires(rcu)
{ {
spin_lock_bh(&pnsocks.lock); rcu_read_lock();
return *pos ? pn_sock_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; return *pos ? pn_sock_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
} }
...@@ -591,9 +590,9 @@ static void *pn_sock_seq_next(struct seq_file *seq, void *v, loff_t *pos) ...@@ -591,9 +590,9 @@ static void *pn_sock_seq_next(struct seq_file *seq, void *v, loff_t *pos)
} }
static void pn_sock_seq_stop(struct seq_file *seq, void *v) static void pn_sock_seq_stop(struct seq_file *seq, void *v)
__releases(pnsocks.lock) __releases(rcu)
{ {
spin_unlock_bh(&pnsocks.lock); rcu_read_unlock();
} }
static int pn_sock_seq_show(struct seq_file *seq, void *v) static int pn_sock_seq_show(struct seq_file *seq, void *v)
...@@ -721,13 +720,11 @@ void pn_sock_unbind_all_res(struct sock *sk) ...@@ -721,13 +720,11 @@ void pn_sock_unbind_all_res(struct sock *sk)
} }
mutex_unlock(&resource_mutex); mutex_unlock(&resource_mutex);
if (match == 0)
return;
synchronize_rcu();
while (match > 0) { while (match > 0) {
sock_put(sk); __sock_put(sk);
match--; match--;
} }
/* Caller is responsible for RCU sync before final sock_put() */
} }
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
......
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