net: Allow xfrm_user_net_exit to batch efficiently.
xfrm.nlsk is provided by the xfrm_user module and is access via rcu from other parts of the xfrm code. Add xfrm.nlsk_stash a copy of xfrm.nlsk that will never be set to NULL. This allows the synchronize_net and netlink_kernel_release to be deferred until a whole batch of xfrm.nlsk sockets have been set to NULL. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
04dc7f6be3
commit
d79d792ef9
|
@ -43,6 +43,7 @@ struct netns_xfrm {
|
|||
struct work_struct policy_hash_work;
|
||||
|
||||
struct sock *nlsk;
|
||||
struct sock *nlsk_stash;
|
||||
|
||||
u32 sysctl_aevent_etime;
|
||||
u32 sysctl_aevent_rseqth;
|
||||
|
|
|
@ -2721,22 +2721,24 @@ static int __net_init xfrm_user_net_init(struct net *net)
|
|||
xfrm_netlink_rcv, NULL, THIS_MODULE);
|
||||
if (nlsk == NULL)
|
||||
return -ENOMEM;
|
||||
net->xfrm.nlsk_stash = nlsk; /* Don't set to NULL */
|
||||
rcu_assign_pointer(net->xfrm.nlsk, nlsk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __net_exit xfrm_user_net_exit(struct net *net)
|
||||
static void __net_exit xfrm_user_net_exit(struct list_head *net_exit_list)
|
||||
{
|
||||
struct sock *nlsk = net->xfrm.nlsk;
|
||||
|
||||
rcu_assign_pointer(net->xfrm.nlsk, NULL);
|
||||
synchronize_rcu();
|
||||
netlink_kernel_release(nlsk);
|
||||
struct net *net;
|
||||
list_for_each_entry(net, net_exit_list, exit_list)
|
||||
rcu_assign_pointer(net->xfrm.nlsk, NULL);
|
||||
synchronize_net();
|
||||
list_for_each_entry(net, net_exit_list, exit_list)
|
||||
netlink_kernel_release(net->xfrm.nlsk_stash);
|
||||
}
|
||||
|
||||
static struct pernet_operations xfrm_user_net_ops = {
|
||||
.init = xfrm_user_net_init,
|
||||
.exit = xfrm_user_net_exit,
|
||||
.init = xfrm_user_net_init,
|
||||
.exit_batch = xfrm_user_net_exit,
|
||||
};
|
||||
|
||||
static int __init xfrm_user_init(void)
|
||||
|
|
Loading…
Reference in New Issue