diff options
author | Rémi Denis-Courmont <remi.denis-courmont@nokia.com> | 2011-04-12 19:27:36 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-04-15 00:32:53 -0400 |
commit | 44f4d5a27ee63ec80d498e0d0673605d5ce1427d (patch) | |
tree | 09b14d853c0df99a35fe2d3811d83640ca98254e /net/phonet | |
parent | fce55922f5299a04c0a56b170a141fab34f13465 (diff) |
Phonet: convert bound sockets hash list to RCU
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>
Diffstat (limited to 'net/phonet')
-rw-r--r-- | net/phonet/socket.c | 45 |
1 files changed, 21 insertions, 24 deletions
diff --git a/net/phonet/socket.c b/net/phonet/socket.c index b1adafab377c..8c5bfcef92cb 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c | |||
@@ -52,7 +52,7 @@ static int pn_socket_release(struct socket *sock) | |||
52 | 52 | ||
53 | static struct { | 53 | static struct { |
54 | struct hlist_head hlist[PN_HASHSIZE]; | 54 | struct hlist_head hlist[PN_HASHSIZE]; |
55 | spinlock_t lock; | 55 | struct mutex lock; |
56 | } pnsocks; | 56 | } pnsocks; |
57 | 57 | ||
58 | void __init pn_sock_init(void) | 58 | void __init pn_sock_init(void) |
@@ -61,7 +61,7 @@ void __init pn_sock_init(void) | |||
61 | 61 | ||
62 | for (i = 0; i < PN_HASHSIZE; i++) | 62 | for (i = 0; i < PN_HASHSIZE; i++) |
63 | INIT_HLIST_HEAD(pnsocks.hlist + i); | 63 | INIT_HLIST_HEAD(pnsocks.hlist + i); |
64 | spin_lock_init(&pnsocks.lock); | 64 | mutex_init(&pnsocks.lock); |
65 | } | 65 | } |
66 | 66 | ||
67 | static struct hlist_head *pn_hash_list(u16 obj) | 67 | 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 | u8 res = spn->spn_resource; | 82 | u8 res = spn->spn_resource; |
83 | struct hlist_head *hlist = pn_hash_list(obj); | 83 | struct hlist_head *hlist = pn_hash_list(obj); |
84 | 84 | ||
85 | spin_lock_bh(&pnsocks.lock); | 85 | rcu_read_lock(); |
86 | 86 | sk_for_each_rcu(sknode, node, hlist) { | |
87 | sk_for_each(sknode, node, hlist) { | ||
88 | struct pn_sock *pn = pn_sk(sknode); | 87 | struct pn_sock *pn = pn_sk(sknode); |
89 | BUG_ON(!pn->sobject); /* unbound socket */ | 88 | BUG_ON(!pn->sobject); /* unbound socket */ |
90 | 89 | ||
@@ -107,8 +106,7 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn) | |||
107 | sock_hold(sknode); | 106 | sock_hold(sknode); |
108 | break; | 107 | break; |
109 | } | 108 | } |
110 | 109 | rcu_read_unlock(); | |
111 | spin_unlock_bh(&pnsocks.lock); | ||
112 | 110 | ||
113 | return rval; | 111 | return rval; |
114 | } | 112 | } |
@@ -119,7 +117,7 @@ void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb) | |||
119 | struct hlist_head *hlist = pnsocks.hlist; | 117 | struct hlist_head *hlist = pnsocks.hlist; |
120 | unsigned h; | 118 | unsigned h; |
121 | 119 | ||
122 | spin_lock(&pnsocks.lock); | 120 | rcu_read_lock(); |
123 | for (h = 0; h < PN_HASHSIZE; h++) { | 121 | for (h = 0; h < PN_HASHSIZE; h++) { |
124 | struct hlist_node *node; | 122 | struct hlist_node *node; |
125 | struct sock *sknode; | 123 | struct sock *sknode; |
@@ -140,25 +138,26 @@ void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb) | |||
140 | } | 138 | } |
141 | hlist++; | 139 | hlist++; |
142 | } | 140 | } |
143 | spin_unlock(&pnsocks.lock); | 141 | rcu_read_unlock(); |
144 | } | 142 | } |
145 | 143 | ||
146 | void pn_sock_hash(struct sock *sk) | 144 | void pn_sock_hash(struct sock *sk) |
147 | { | 145 | { |
148 | struct hlist_head *hlist = pn_hash_list(pn_sk(sk)->sobject); | 146 | struct hlist_head *hlist = pn_hash_list(pn_sk(sk)->sobject); |
149 | 147 | ||
150 | spin_lock_bh(&pnsocks.lock); | 148 | mutex_lock(&pnsocks.lock); |
151 | sk_add_node(sk, hlist); | 149 | sk_add_node_rcu(sk, hlist); |
152 | spin_unlock_bh(&pnsocks.lock); | 150 | mutex_unlock(&pnsocks.lock); |
153 | } | 151 | } |
154 | EXPORT_SYMBOL(pn_sock_hash); | 152 | EXPORT_SYMBOL(pn_sock_hash); |
155 | 153 | ||
156 | void pn_sock_unhash(struct sock *sk) | 154 | void pn_sock_unhash(struct sock *sk) |
157 | { | 155 | { |
158 | spin_lock_bh(&pnsocks.lock); | 156 | mutex_lock(&pnsocks.lock); |
159 | sk_del_node_init(sk); | 157 | sk_del_node_init_rcu(sk); |
160 | spin_unlock_bh(&pnsocks.lock); | 158 | mutex_unlock(&pnsocks.lock); |
161 | pn_sock_unbind_all_res(sk); | 159 | pn_sock_unbind_all_res(sk); |
160 | synchronize_rcu(); | ||
162 | } | 161 | } |
163 | EXPORT_SYMBOL(pn_sock_unhash); | 162 | EXPORT_SYMBOL(pn_sock_unhash); |
164 | 163 | ||
@@ -548,7 +547,7 @@ static struct sock *pn_sock_get_idx(struct seq_file *seq, loff_t pos) | |||
548 | unsigned h; | 547 | unsigned h; |
549 | 548 | ||
550 | for (h = 0; h < PN_HASHSIZE; h++) { | 549 | for (h = 0; h < PN_HASHSIZE; h++) { |
551 | sk_for_each(sknode, node, hlist) { | 550 | sk_for_each_rcu(sknode, node, hlist) { |
552 | if (!net_eq(net, sock_net(sknode))) | 551 | if (!net_eq(net, sock_net(sknode))) |
553 | continue; | 552 | continue; |
554 | if (!pos) | 553 | if (!pos) |
@@ -572,9 +571,9 @@ static struct sock *pn_sock_get_next(struct seq_file *seq, struct sock *sk) | |||
572 | } | 571 | } |
573 | 572 | ||
574 | static void *pn_sock_seq_start(struct seq_file *seq, loff_t *pos) | 573 | static void *pn_sock_seq_start(struct seq_file *seq, loff_t *pos) |
575 | __acquires(pnsocks.lock) | 574 | __acquires(rcu) |
576 | { | 575 | { |
577 | spin_lock_bh(&pnsocks.lock); | 576 | rcu_read_lock(); |
578 | return *pos ? pn_sock_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; | 577 | return *pos ? pn_sock_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; |
579 | } | 578 | } |
580 | 579 | ||
@@ -591,9 +590,9 @@ static void *pn_sock_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
591 | } | 590 | } |
592 | 591 | ||
593 | static void pn_sock_seq_stop(struct seq_file *seq, void *v) | 592 | static void pn_sock_seq_stop(struct seq_file *seq, void *v) |
594 | __releases(pnsocks.lock) | 593 | __releases(rcu) |
595 | { | 594 | { |
596 | spin_unlock_bh(&pnsocks.lock); | 595 | rcu_read_unlock(); |
597 | } | 596 | } |
598 | 597 | ||
599 | static int pn_sock_seq_show(struct seq_file *seq, void *v) | 598 | 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 | } | 720 | } |
722 | mutex_unlock(&resource_mutex); | 721 | mutex_unlock(&resource_mutex); |
723 | 722 | ||
724 | if (match == 0) | ||
725 | return; | ||
726 | synchronize_rcu(); | ||
727 | while (match > 0) { | 723 | while (match > 0) { |
728 | sock_put(sk); | 724 | __sock_put(sk); |
729 | match--; | 725 | match--; |
730 | } | 726 | } |
727 | /* Caller is responsible for RCU sync before final sock_put() */ | ||
731 | } | 728 | } |
732 | 729 | ||
733 | #ifdef CONFIG_PROC_FS | 730 | #ifdef CONFIG_PROC_FS |