diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2009-12-02 21:29:05 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-12-03 15:22:03 -0500 |
commit | d79d792ef9f99cca463b6619a93e860d1c833a6e (patch) | |
tree | 06d8a085701546be48ac104fd4f2413a6371180c /net | |
parent | 04dc7f6be3a7b308f8545bb45772c9fb75f71aca (diff) |
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>
Diffstat (limited to 'net')
-rw-r--r-- | net/xfrm/xfrm_user.c | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index fb42d778d278..1ada6186933c 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -2721,22 +2721,24 @@ static int __net_init xfrm_user_net_init(struct net *net) | |||
2721 | xfrm_netlink_rcv, NULL, THIS_MODULE); | 2721 | xfrm_netlink_rcv, NULL, THIS_MODULE); |
2722 | if (nlsk == NULL) | 2722 | if (nlsk == NULL) |
2723 | return -ENOMEM; | 2723 | return -ENOMEM; |
2724 | net->xfrm.nlsk_stash = nlsk; /* Don't set to NULL */ | ||
2724 | rcu_assign_pointer(net->xfrm.nlsk, nlsk); | 2725 | rcu_assign_pointer(net->xfrm.nlsk, nlsk); |
2725 | return 0; | 2726 | return 0; |
2726 | } | 2727 | } |
2727 | 2728 | ||
2728 | static void __net_exit xfrm_user_net_exit(struct net *net) | 2729 | static void __net_exit xfrm_user_net_exit(struct list_head *net_exit_list) |
2729 | { | 2730 | { |
2730 | struct sock *nlsk = net->xfrm.nlsk; | 2731 | struct net *net; |
2731 | 2732 | list_for_each_entry(net, net_exit_list, exit_list) | |
2732 | rcu_assign_pointer(net->xfrm.nlsk, NULL); | 2733 | rcu_assign_pointer(net->xfrm.nlsk, NULL); |
2733 | synchronize_rcu(); | 2734 | synchronize_net(); |
2734 | netlink_kernel_release(nlsk); | 2735 | list_for_each_entry(net, net_exit_list, exit_list) |
2736 | netlink_kernel_release(net->xfrm.nlsk_stash); | ||
2735 | } | 2737 | } |
2736 | 2738 | ||
2737 | static struct pernet_operations xfrm_user_net_ops = { | 2739 | static struct pernet_operations xfrm_user_net_ops = { |
2738 | .init = xfrm_user_net_init, | 2740 | .init = xfrm_user_net_init, |
2739 | .exit = xfrm_user_net_exit, | 2741 | .exit_batch = xfrm_user_net_exit, |
2740 | }; | 2742 | }; |
2741 | 2743 | ||
2742 | static int __init xfrm_user_init(void) | 2744 | static int __init xfrm_user_init(void) |