summaryrefslogtreecommitdiff
path: root/net/phonet
diff options
context:
space:
mode:
Diffstat (limited to 'net/phonet')
-rw-r--r--net/phonet/pn_dev.c6
-rw-r--r--net/phonet/pn_netlink.c4
-rw-r--r--net/phonet/socket.c45
3 files changed, 25 insertions, 30 deletions
diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c
index 1566672235dd..d2df8f33160b 100644
--- a/net/phonet/pn_dev.c
+++ b/net/phonet/pn_dev.c
@@ -418,18 +418,14 @@ int phonet_route_del(struct net_device *dev, u8 daddr)
return 0;
}
-struct net_device *phonet_route_get(struct net *net, u8 daddr)
+struct net_device *phonet_route_get_rcu(struct net *net, u8 daddr)
{
struct phonet_net *pnn = phonet_pernet(net);
struct phonet_routes *routes = &pnn->routes;
struct net_device *dev;
- ASSERT_RTNL(); /* no need to hold the device */
-
daddr >>= 2;
- rcu_read_lock();
dev = rcu_dereference(routes->table[daddr]);
- rcu_read_unlock();
return dev;
}
diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c
index 58b3b1f991ed..438accb7a5a8 100644
--- a/net/phonet/pn_netlink.c
+++ b/net/phonet/pn_netlink.c
@@ -264,10 +264,11 @@ static int route_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
struct net *net = sock_net(skb->sk);
u8 addr, addr_idx = 0, addr_start_idx = cb->args[0];
+ rcu_read_lock();
for (addr = 0; addr < 64; addr++) {
struct net_device *dev;
- dev = phonet_route_get(net, addr << 2);
+ dev = phonet_route_get_rcu(net, addr << 2);
if (!dev)
continue;
@@ -279,6 +280,7 @@ static int route_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
}
out:
+ rcu_read_unlock();
cb->args[0] = addr_idx;
cb->args[1] = 0;
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)
static struct {
struct hlist_head hlist[PN_HASHSIZE];
- spinlock_t lock;
+ struct mutex lock;
} pnsocks;
void __init pn_sock_init(void)
@@ -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)
@@ -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 */
@@ -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;
}
@@ -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;
@@ -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);
@@ -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)
@@ -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;
}
@@ -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)
@@ -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