diff options
Diffstat (limited to 'net/phonet/socket.c')
| -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 b1adafab377..8c5bfcef92c 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 |
