Commit 83044bf9 authored by David S. Miller's avatar David S. Miller

Merge branch 'netns-init-cleanups' into main

Kuniyuki Iwashima says:

====================
net: Random cleanup for netns initialisation.

patch 1 & 2 suppress unwanted memory allocation for net->gen->ptr[].

patch 3 ~ 6 move part of netns initialisation to prenet_init() that
do not require pernet_ops_rwsem.

v2:
  patch 1 : Removed Fixes: tag
  patch 2 : Use XOR for WARN_ON()

v1: https://lore.kernel.org/netdev/20240729210801.16196-1-kuniyu@amazon.com/
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c4b28e56 8eaf71f7
...@@ -451,8 +451,8 @@ struct pernet_operations { ...@@ -451,8 +451,8 @@ struct pernet_operations {
/* Following method is called with RTNL held. */ /* Following method is called with RTNL held. */
void (*exit_batch_rtnl)(struct list_head *net_exit_list, void (*exit_batch_rtnl)(struct list_head *net_exit_list,
struct list_head *dev_kill_list); struct list_head *dev_kill_list);
unsigned int *id; unsigned int * const id;
size_t size; const size_t size;
}; };
/* /*
......
...@@ -125,7 +125,7 @@ static int ops_init(const struct pernet_operations *ops, struct net *net) ...@@ -125,7 +125,7 @@ static int ops_init(const struct pernet_operations *ops, struct net *net)
int err = -ENOMEM; int err = -ENOMEM;
void *data = NULL; void *data = NULL;
if (ops->id && ops->size) { if (ops->id) {
data = kzalloc(ops->size, GFP_KERNEL); data = kzalloc(ops->size, GFP_KERNEL);
if (!data) if (!data)
goto out; goto out;
...@@ -140,7 +140,7 @@ static int ops_init(const struct pernet_operations *ops, struct net *net) ...@@ -140,7 +140,7 @@ static int ops_init(const struct pernet_operations *ops, struct net *net)
if (!err) if (!err)
return 0; return 0;
if (ops->id && ops->size) { if (ops->id) {
ng = rcu_dereference_protected(net->gen, ng = rcu_dereference_protected(net->gen,
lockdep_is_held(&pernet_ops_rwsem)); lockdep_is_held(&pernet_ops_rwsem));
ng->ptr[*ops->id] = NULL; ng->ptr[*ops->id] = NULL;
...@@ -182,7 +182,8 @@ static void ops_free_list(const struct pernet_operations *ops, ...@@ -182,7 +182,8 @@ static void ops_free_list(const struct pernet_operations *ops,
struct list_head *net_exit_list) struct list_head *net_exit_list)
{ {
struct net *net; struct net *net;
if (ops->size && ops->id) {
if (ops->id) {
list_for_each_entry(net, net_exit_list, exit_list) list_for_each_entry(net, net_exit_list, exit_list)
kfree(net_generic(net, *ops->id)); kfree(net_generic(net, *ops->id));
} }
...@@ -308,16 +309,38 @@ struct net *get_net_ns_by_id(const struct net *net, int id) ...@@ -308,16 +309,38 @@ struct net *get_net_ns_by_id(const struct net *net, int id)
} }
EXPORT_SYMBOL_GPL(get_net_ns_by_id); EXPORT_SYMBOL_GPL(get_net_ns_by_id);
static __net_init void preinit_net_sysctl(struct net *net)
{
net->core.sysctl_somaxconn = SOMAXCONN;
/* Limits per socket sk_omem_alloc usage.
* TCP zerocopy regular usage needs 128 KB.
*/
net->core.sysctl_optmem_max = 128 * 1024;
net->core.sysctl_txrehash = SOCK_TXREHASH_ENABLED;
}
/* init code that must occur even if setup_net() is not called. */ /* init code that must occur even if setup_net() is not called. */
static __net_init void preinit_net(struct net *net) static __net_init void preinit_net(struct net *net, struct user_namespace *user_ns)
{ {
refcount_set(&net->passive, 1);
refcount_set(&net->ns.count, 1);
ref_tracker_dir_init(&net->refcnt_tracker, 128, "net refcnt");
ref_tracker_dir_init(&net->notrefcnt_tracker, 128, "net notrefcnt"); ref_tracker_dir_init(&net->notrefcnt_tracker, 128, "net notrefcnt");
get_random_bytes(&net->hash_mix, sizeof(u32));
net->dev_base_seq = 1;
net->user_ns = user_ns;
idr_init(&net->netns_ids);
spin_lock_init(&net->nsid_lock);
mutex_init(&net->ipv4.ra_mutex);
preinit_net_sysctl(net);
} }
/* /*
* setup_net runs the initializers for the network namespace object. * setup_net runs the initializers for the network namespace object.
*/ */
static __net_init int setup_net(struct net *net, struct user_namespace *user_ns) static __net_init int setup_net(struct net *net)
{ {
/* Must be called with pernet_ops_rwsem held */ /* Must be called with pernet_ops_rwsem held */
const struct pernet_operations *ops, *saved_ops; const struct pernet_operations *ops, *saved_ops;
...@@ -325,19 +348,9 @@ static __net_init int setup_net(struct net *net, struct user_namespace *user_ns) ...@@ -325,19 +348,9 @@ static __net_init int setup_net(struct net *net, struct user_namespace *user_ns)
LIST_HEAD(dev_kill_list); LIST_HEAD(dev_kill_list);
int error = 0; int error = 0;
refcount_set(&net->ns.count, 1);
ref_tracker_dir_init(&net->refcnt_tracker, 128, "net refcnt");
refcount_set(&net->passive, 1);
get_random_bytes(&net->hash_mix, sizeof(u32));
preempt_disable(); preempt_disable();
net->net_cookie = gen_cookie_next(&net_cookie); net->net_cookie = gen_cookie_next(&net_cookie);
preempt_enable(); preempt_enable();
net->dev_base_seq = 1;
net->user_ns = user_ns;
idr_init(&net->netns_ids);
spin_lock_init(&net->nsid_lock);
mutex_init(&net->ipv4.ra_mutex);
list_for_each_entry(ops, &pernet_list, list) { list_for_each_entry(ops, &pernet_list, list) {
error = ops_init(ops, net); error = ops_init(ops, net);
...@@ -382,32 +395,6 @@ static __net_init int setup_net(struct net *net, struct user_namespace *user_ns) ...@@ -382,32 +395,6 @@ static __net_init int setup_net(struct net *net, struct user_namespace *user_ns)
goto out; goto out;
} }
static int __net_init net_defaults_init_net(struct net *net)
{
net->core.sysctl_somaxconn = SOMAXCONN;
/* Limits per socket sk_omem_alloc usage.
* TCP zerocopy regular usage needs 128 KB.
*/
net->core.sysctl_optmem_max = 128 * 1024;
net->core.sysctl_txrehash = SOCK_TXREHASH_ENABLED;
return 0;
}
static struct pernet_operations net_defaults_ops = {
.init = net_defaults_init_net,
};
static __init int net_defaults_init(void)
{
if (register_pernet_subsys(&net_defaults_ops))
panic("Cannot initialize net default settings");
return 0;
}
core_initcall(net_defaults_init);
#ifdef CONFIG_NET_NS #ifdef CONFIG_NET_NS
static struct ucounts *inc_net_namespaces(struct user_namespace *ns) static struct ucounts *inc_net_namespaces(struct user_namespace *ns)
{ {
...@@ -496,8 +483,7 @@ struct net *copy_net_ns(unsigned long flags, ...@@ -496,8 +483,7 @@ struct net *copy_net_ns(unsigned long flags,
goto dec_ucounts; goto dec_ucounts;
} }
preinit_net(net); preinit_net(net, user_ns);
refcount_set(&net->passive, 1);
net->ucounts = ucounts; net->ucounts = ucounts;
get_user_ns(user_ns); get_user_ns(user_ns);
...@@ -505,7 +491,7 @@ struct net *copy_net_ns(unsigned long flags, ...@@ -505,7 +491,7 @@ struct net *copy_net_ns(unsigned long flags,
if (rv < 0) if (rv < 0)
goto put_userns; goto put_userns;
rv = setup_net(net, user_ns); rv = setup_net(net);
up_read(&pernet_ops_rwsem); up_read(&pernet_ops_rwsem);
...@@ -1199,9 +1185,10 @@ void __init net_ns_init(void) ...@@ -1199,9 +1185,10 @@ void __init net_ns_init(void)
#ifdef CONFIG_KEYS #ifdef CONFIG_KEYS
init_net.key_domain = &init_net_key_domain; init_net.key_domain = &init_net_key_domain;
#endif #endif
preinit_net(&init_net, &init_user_ns);
down_write(&pernet_ops_rwsem); down_write(&pernet_ops_rwsem);
preinit_net(&init_net); if (setup_net(&init_net))
if (setup_net(&init_net, &init_user_ns))
panic("Could not setup the initial network namespace"); panic("Could not setup the initial network namespace");
init_net_initialized = true; init_net_initialized = true;
...@@ -1244,7 +1231,7 @@ static int __register_pernet_operations(struct list_head *list, ...@@ -1244,7 +1231,7 @@ static int __register_pernet_operations(struct list_head *list,
LIST_HEAD(net_exit_list); LIST_HEAD(net_exit_list);
list_add_tail(&ops->list, list); list_add_tail(&ops->list, list);
if (ops->init || (ops->id && ops->size)) { if (ops->init || ops->id) {
/* We held write locked pernet_ops_rwsem, and parallel /* We held write locked pernet_ops_rwsem, and parallel
* setup_net() and cleanup_net() are not possible. * setup_net() and cleanup_net() are not possible.
*/ */
...@@ -1310,6 +1297,9 @@ static int register_pernet_operations(struct list_head *list, ...@@ -1310,6 +1297,9 @@ static int register_pernet_operations(struct list_head *list,
{ {
int error; int error;
if (WARN_ON(!!ops->id ^ !!ops->size))
return -EINVAL;
if (ops->id) { if (ops->id) {
error = ida_alloc_min(&net_generic_ids, MIN_PERNET_OPS_ID, error = ida_alloc_min(&net_generic_ids, MIN_PERNET_OPS_ID,
GFP_KERNEL); GFP_KERNEL);
......
...@@ -1393,8 +1393,6 @@ static int pppol2tp_getsockopt(struct socket *sock, int level, int optname, ...@@ -1393,8 +1393,6 @@ static int pppol2tp_getsockopt(struct socket *sock, int level, int optname,
* L2TPv2, we dump only L2TPv2 tunnels and sessions here. * L2TPv2, we dump only L2TPv2 tunnels and sessions here.
*****************************************************************************/ *****************************************************************************/
static unsigned int pppol2tp_net_id;
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
struct pppol2tp_seq_data { struct pppol2tp_seq_data {
...@@ -1628,7 +1626,6 @@ static __net_exit void pppol2tp_exit_net(struct net *net) ...@@ -1628,7 +1626,6 @@ static __net_exit void pppol2tp_exit_net(struct net *net)
static struct pernet_operations pppol2tp_net_ops = { static struct pernet_operations pppol2tp_net_ops = {
.init = pppol2tp_init_net, .init = pppol2tp_init_net,
.exit = pppol2tp_exit_net, .exit = pppol2tp_exit_net,
.id = &pppol2tp_net_id,
}; };
/***************************************************************************** /*****************************************************************************
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment