| From e987d294c45daf6018108e046fcab0be00e91f68 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 17 Aug 2021 23:23:00 +0800 |
| Subject: net: net_namespace: Optimize the code |
| |
| From: Yajun Deng <yajun.deng@linux.dev> |
| |
| [ Upstream commit 41467d2ff4dfe1837cbb0f45e2088e6e787580c6 ] |
| |
| There is only one caller for ops_free(), so inline it. |
| Separate net_drop_ns() and net_free(), so the net_free() |
| can be called directly. |
| Add free_exit_list() helper function for free net_exit_list. |
| |
| ==================== |
| v2: |
| - v1 does not apply, rebase it. |
| ==================== |
| |
| Signed-off-by: Yajun Deng <yajun.deng@linux.dev> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Stable-dep-of: 46841c7053e6 ("gtp: Use for_each_netdev_rcu() in gtp_genl_dump_pdp().") |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| net/core/net_namespace.c | 52 +++++++++++++++++++--------------------- |
| 1 file changed, 24 insertions(+), 28 deletions(-) |
| |
| diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c |
| index c94179d30d426..c4bcedc06822b 100644 |
| --- a/net/core/net_namespace.c |
| +++ b/net/core/net_namespace.c |
| @@ -98,7 +98,7 @@ static int net_assign_generic(struct net *net, unsigned int id, void *data) |
| } |
| |
| ng = net_alloc_generic(); |
| - if (ng == NULL) |
| + if (!ng) |
| return -ENOMEM; |
| |
| /* |
| @@ -155,13 +155,6 @@ static int ops_init(const struct pernet_operations *ops, struct net *net) |
| return err; |
| } |
| |
| -static void ops_free(const struct pernet_operations *ops, struct net *net) |
| -{ |
| - if (ops->id && ops->size) { |
| - kfree(net_generic(net, *ops->id)); |
| - } |
| -} |
| - |
| static void ops_pre_exit_list(const struct pernet_operations *ops, |
| struct list_head *net_exit_list) |
| { |
| @@ -193,7 +186,7 @@ static void ops_free_list(const struct pernet_operations *ops, |
| struct net *net; |
| if (ops->size && ops->id) { |
| list_for_each_entry(net, net_exit_list, exit_list) |
| - ops_free(ops, net); |
| + kfree(net_generic(net, *ops->id)); |
| } |
| } |
| |
| @@ -448,15 +441,18 @@ static struct net *net_alloc(void) |
| |
| static void net_free(struct net *net) |
| { |
| - kfree(rcu_access_pointer(net->gen)); |
| - kmem_cache_free(net_cachep, net); |
| + if (refcount_dec_and_test(&net->passive)) { |
| + kfree(rcu_access_pointer(net->gen)); |
| + kmem_cache_free(net_cachep, net); |
| + } |
| } |
| |
| void net_drop_ns(void *p) |
| { |
| - struct net *ns = p; |
| - if (ns && refcount_dec_and_test(&ns->passive)) |
| - net_free(ns); |
| + struct net *net = (struct net *)p; |
| + |
| + if (net) |
| + net_free(net); |
| } |
| |
| struct net *copy_net_ns(unsigned long flags, |
| @@ -496,7 +492,7 @@ struct net *copy_net_ns(unsigned long flags, |
| key_remove_domain(net->key_domain); |
| #endif |
| put_user_ns(user_ns); |
| - net_drop_ns(net); |
| + net_free(net); |
| dec_ucounts: |
| dec_net_namespaces(ucounts); |
| return ERR_PTR(rv); |
| @@ -630,7 +626,7 @@ static void cleanup_net(struct work_struct *work) |
| key_remove_domain(net->key_domain); |
| #endif |
| put_user_ns(net->user_ns); |
| - net_drop_ns(net); |
| + net_free(net); |
| } |
| } |
| |
| @@ -1150,6 +1146,14 @@ static int __init net_ns_init(void) |
| |
| pure_initcall(net_ns_init); |
| |
| +static void free_exit_list(struct pernet_operations *ops, struct list_head *net_exit_list) |
| +{ |
| + ops_pre_exit_list(ops, net_exit_list); |
| + synchronize_rcu(); |
| + ops_exit_list(ops, net_exit_list); |
| + ops_free_list(ops, net_exit_list); |
| +} |
| + |
| #ifdef CONFIG_NET_NS |
| static int __register_pernet_operations(struct list_head *list, |
| struct pernet_operations *ops) |
| @@ -1175,10 +1179,7 @@ static int __register_pernet_operations(struct list_head *list, |
| out_undo: |
| /* If I have an error cleanup all namespaces I initialized */ |
| list_del(&ops->list); |
| - ops_pre_exit_list(ops, &net_exit_list); |
| - synchronize_rcu(); |
| - ops_exit_list(ops, &net_exit_list); |
| - ops_free_list(ops, &net_exit_list); |
| + free_exit_list(ops, &net_exit_list); |
| return error; |
| } |
| |
| @@ -1191,10 +1192,8 @@ static void __unregister_pernet_operations(struct pernet_operations *ops) |
| /* See comment in __register_pernet_operations() */ |
| for_each_net(net) |
| list_add_tail(&net->exit_list, &net_exit_list); |
| - ops_pre_exit_list(ops, &net_exit_list); |
| - synchronize_rcu(); |
| - ops_exit_list(ops, &net_exit_list); |
| - ops_free_list(ops, &net_exit_list); |
| + |
| + free_exit_list(ops, &net_exit_list); |
| } |
| |
| #else |
| @@ -1217,10 +1216,7 @@ static void __unregister_pernet_operations(struct pernet_operations *ops) |
| } else { |
| LIST_HEAD(net_exit_list); |
| list_add(&init_net.exit_list, &net_exit_list); |
| - ops_pre_exit_list(ops, &net_exit_list); |
| - synchronize_rcu(); |
| - ops_exit_list(ops, &net_exit_list); |
| - ops_free_list(ops, &net_exit_list); |
| + free_exit_list(ops, &net_exit_list); |
| } |
| } |
| |
| -- |
| 2.39.5 |
| |