af_key: locking change
Get rid of custom locking that was using wait queue, lock, and atomic to basically build a queued mutex. Use RCU for read side. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
808f5114a9
commit
7f6b9dbd5a
|
@ -41,9 +41,7 @@ struct netns_pfkey {
|
||||||
struct hlist_head table;
|
struct hlist_head table;
|
||||||
atomic_t socks_nr;
|
atomic_t socks_nr;
|
||||||
};
|
};
|
||||||
static DECLARE_WAIT_QUEUE_HEAD(pfkey_table_wait);
|
static DEFINE_MUTEX(pfkey_mutex);
|
||||||
static DEFINE_RWLOCK(pfkey_table_lock);
|
|
||||||
static atomic_t pfkey_table_users = ATOMIC_INIT(0);
|
|
||||||
|
|
||||||
struct pfkey_sock {
|
struct pfkey_sock {
|
||||||
/* struct sock must be the first member of struct pfkey_sock */
|
/* struct sock must be the first member of struct pfkey_sock */
|
||||||
|
@ -108,50 +106,6 @@ static void pfkey_sock_destruct(struct sock *sk)
|
||||||
atomic_dec(&net_pfkey->socks_nr);
|
atomic_dec(&net_pfkey->socks_nr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pfkey_table_grab(void)
|
|
||||||
{
|
|
||||||
write_lock_bh(&pfkey_table_lock);
|
|
||||||
|
|
||||||
if (atomic_read(&pfkey_table_users)) {
|
|
||||||
DECLARE_WAITQUEUE(wait, current);
|
|
||||||
|
|
||||||
add_wait_queue_exclusive(&pfkey_table_wait, &wait);
|
|
||||||
for(;;) {
|
|
||||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
|
||||||
if (atomic_read(&pfkey_table_users) == 0)
|
|
||||||
break;
|
|
||||||
write_unlock_bh(&pfkey_table_lock);
|
|
||||||
schedule();
|
|
||||||
write_lock_bh(&pfkey_table_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
__set_current_state(TASK_RUNNING);
|
|
||||||
remove_wait_queue(&pfkey_table_wait, &wait);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ void pfkey_table_ungrab(void)
|
|
||||||
{
|
|
||||||
write_unlock_bh(&pfkey_table_lock);
|
|
||||||
wake_up(&pfkey_table_wait);
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ void pfkey_lock_table(void)
|
|
||||||
{
|
|
||||||
/* read_lock() synchronizes us to pfkey_table_grab */
|
|
||||||
|
|
||||||
read_lock(&pfkey_table_lock);
|
|
||||||
atomic_inc(&pfkey_table_users);
|
|
||||||
read_unlock(&pfkey_table_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ void pfkey_unlock_table(void)
|
|
||||||
{
|
|
||||||
if (atomic_dec_and_test(&pfkey_table_users))
|
|
||||||
wake_up(&pfkey_table_wait);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static const struct proto_ops pfkey_ops;
|
static const struct proto_ops pfkey_ops;
|
||||||
|
|
||||||
static void pfkey_insert(struct sock *sk)
|
static void pfkey_insert(struct sock *sk)
|
||||||
|
@ -159,16 +113,16 @@ static void pfkey_insert(struct sock *sk)
|
||||||
struct net *net = sock_net(sk);
|
struct net *net = sock_net(sk);
|
||||||
struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
|
struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
|
||||||
|
|
||||||
pfkey_table_grab();
|
mutex_lock(&pfkey_mutex);
|
||||||
sk_add_node(sk, &net_pfkey->table);
|
sk_add_node_rcu(sk, &net_pfkey->table);
|
||||||
pfkey_table_ungrab();
|
mutex_unlock(&pfkey_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pfkey_remove(struct sock *sk)
|
static void pfkey_remove(struct sock *sk)
|
||||||
{
|
{
|
||||||
pfkey_table_grab();
|
mutex_lock(&pfkey_mutex);
|
||||||
sk_del_node_init(sk);
|
sk_del_node_init_rcu(sk);
|
||||||
pfkey_table_ungrab();
|
mutex_unlock(&pfkey_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct proto key_proto = {
|
static struct proto key_proto = {
|
||||||
|
@ -223,6 +177,8 @@ static int pfkey_release(struct socket *sock)
|
||||||
sock_orphan(sk);
|
sock_orphan(sk);
|
||||||
sock->sk = NULL;
|
sock->sk = NULL;
|
||||||
skb_queue_purge(&sk->sk_write_queue);
|
skb_queue_purge(&sk->sk_write_queue);
|
||||||
|
|
||||||
|
synchronize_rcu();
|
||||||
sock_put(sk);
|
sock_put(sk);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -277,8 +233,8 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
|
||||||
if (!skb)
|
if (!skb)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
pfkey_lock_table();
|
rcu_read_lock();
|
||||||
sk_for_each(sk, node, &net_pfkey->table) {
|
sk_for_each_rcu(sk, node, &net_pfkey->table) {
|
||||||
struct pfkey_sock *pfk = pfkey_sk(sk);
|
struct pfkey_sock *pfk = pfkey_sk(sk);
|
||||||
int err2;
|
int err2;
|
||||||
|
|
||||||
|
@ -309,7 +265,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
|
||||||
if ((broadcast_flags & BROADCAST_REGISTERED) && err)
|
if ((broadcast_flags & BROADCAST_REGISTERED) && err)
|
||||||
err = err2;
|
err = err2;
|
||||||
}
|
}
|
||||||
pfkey_unlock_table();
|
rcu_read_unlock();
|
||||||
|
|
||||||
if (one_sk != NULL)
|
if (one_sk != NULL)
|
||||||
err = pfkey_broadcast_one(skb, &skb2, allocation, one_sk);
|
err = pfkey_broadcast_one(skb, &skb2, allocation, one_sk);
|
||||||
|
@ -3702,8 +3658,8 @@ static void *pfkey_seq_start(struct seq_file *f, loff_t *ppos)
|
||||||
struct net *net = seq_file_net(f);
|
struct net *net = seq_file_net(f);
|
||||||
struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
|
struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
|
||||||
|
|
||||||
read_lock(&pfkey_table_lock);
|
rcu_read_lock();
|
||||||
return seq_hlist_start_head(&net_pfkey->table, *ppos);
|
return seq_hlist_start_head_rcu(&net_pfkey->table, *ppos);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *pfkey_seq_next(struct seq_file *f, void *v, loff_t *ppos)
|
static void *pfkey_seq_next(struct seq_file *f, void *v, loff_t *ppos)
|
||||||
|
@ -3711,12 +3667,12 @@ static void *pfkey_seq_next(struct seq_file *f, void *v, loff_t *ppos)
|
||||||
struct net *net = seq_file_net(f);
|
struct net *net = seq_file_net(f);
|
||||||
struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
|
struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
|
||||||
|
|
||||||
return seq_hlist_next(v, &net_pfkey->table, ppos);
|
return seq_hlist_next_rcu(v, &net_pfkey->table, ppos);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pfkey_seq_stop(struct seq_file *f, void *v)
|
static void pfkey_seq_stop(struct seq_file *f, void *v)
|
||||||
{
|
{
|
||||||
read_unlock(&pfkey_table_lock);
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct seq_operations pfkey_seq_ops = {
|
static const struct seq_operations pfkey_seq_ops = {
|
||||||
|
|
Loading…
Reference in New Issue