Skip to content

Commit

Permalink
Phonet: convert bound sockets hash list to RCU
Browse files Browse the repository at this point in the history
This gets rid of the last spinlock in the Phonet stack proper.

Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Rémi Denis-Courmont authored and davem330 committed Apr 15, 2011
1 parent fce5592 commit 44f4d5a
Showing 1 changed file with 21 additions and 24 deletions.
45 changes: 21 additions & 24 deletions net/phonet/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ static int pn_socket_release(struct socket *sock)

static struct {
struct hlist_head hlist[PN_HASHSIZE];
spinlock_t lock;
struct mutex lock;
} pnsocks;

void __init pn_sock_init(void)
Expand All @@ -61,7 +61,7 @@ void __init pn_sock_init(void)

for (i = 0; i < PN_HASHSIZE; 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)
Expand All @@ -82,9 +82,8 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn)
u8 res = spn->spn_resource;
struct hlist_head *hlist = pn_hash_list(obj);

spin_lock_bh(&pnsocks.lock);

sk_for_each(sknode, node, hlist) {
rcu_read_lock();
sk_for_each_rcu(sknode, node, hlist) {
struct pn_sock *pn = pn_sk(sknode);
BUG_ON(!pn->sobject); /* unbound socket */

Expand All @@ -107,8 +106,7 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn)
sock_hold(sknode);
break;
}

spin_unlock_bh(&pnsocks.lock);
rcu_read_unlock();

return rval;
}
Expand All @@ -119,7 +117,7 @@ void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb)
struct hlist_head *hlist = pnsocks.hlist;
unsigned h;

spin_lock(&pnsocks.lock);
rcu_read_lock();
for (h = 0; h < PN_HASHSIZE; h++) {
struct hlist_node *node;
struct sock *sknode;
Expand All @@ -140,25 +138,26 @@ void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb)
}
hlist++;
}
spin_unlock(&pnsocks.lock);
rcu_read_unlock();
}

void pn_sock_hash(struct sock *sk)
{
struct hlist_head *hlist = pn_hash_list(pn_sk(sk)->sobject);

spin_lock_bh(&pnsocks.lock);
sk_add_node(sk, hlist);
spin_unlock_bh(&pnsocks.lock);
mutex_lock(&pnsocks.lock);
sk_add_node_rcu(sk, hlist);
mutex_unlock(&pnsocks.lock);
}
EXPORT_SYMBOL(pn_sock_hash);

void pn_sock_unhash(struct sock *sk)
{
spin_lock_bh(&pnsocks.lock);
sk_del_node_init(sk);
spin_unlock_bh(&pnsocks.lock);
mutex_lock(&pnsocks.lock);
sk_del_node_init_rcu(sk);
mutex_unlock(&pnsocks.lock);
pn_sock_unbind_all_res(sk);
synchronize_rcu();
}
EXPORT_SYMBOL(pn_sock_unhash);

Expand Down Expand Up @@ -548,7 +547,7 @@ static struct sock *pn_sock_get_idx(struct seq_file *seq, loff_t pos)
unsigned 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)))
continue;
if (!pos)
Expand All @@ -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)
__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;
}

Expand All @@ -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)
__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)
Expand Down Expand Up @@ -721,13 +720,11 @@ void pn_sock_unbind_all_res(struct sock *sk)
}
mutex_unlock(&resource_mutex);

if (match == 0)
return;
synchronize_rcu();
while (match > 0) {
sock_put(sk);
__sock_put(sk);
match--;
}
/* Caller is responsible for RCU sync before final sock_put() */
}

#ifdef CONFIG_PROC_FS
Expand Down

0 comments on commit 44f4d5a

Please sign in to comment.