diff options
author | David S. Miller <[email protected]> | 2024-08-03 22:38:45 +0100 |
---|---|---|
committer | David S. Miller <[email protected]> | 2024-08-03 22:38:45 +0100 |
commit | 83044bf90e081ffe87ae3521914b46bfdaba3b1d (patch) | |
tree | 162d353104a07121ee14a133fd6ee0c9f38f1f92 | |
parent | c4b28e5699d2a789fc9464e7ce89f2a1e9d5085d (diff) | |
parent | 8eaf71f77c923f13e41a146703b93fa7988d101f (diff) |
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/[email protected]/
====================
Signed-off-by: David S. Miller <[email protected]>
-rw-r--r-- | include/net/net_namespace.h | 4 | ||||
-rw-r--r-- | net/core/net_namespace.c | 84 | ||||
-rw-r--r-- | net/l2tp/l2tp_ppp.c | 3 |
3 files changed, 39 insertions, 52 deletions
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 20c34bd7a077..e67b483cc8bb 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -451,8 +451,8 @@ struct pernet_operations { /* Following method is called with RTNL held. */ void (*exit_batch_rtnl)(struct list_head *net_exit_list, struct list_head *dev_kill_list); - unsigned int *id; - size_t size; + unsigned int * const id; + const size_t size; }; /* diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 6a823ba906c6..11e4dd4f09ed 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -125,7 +125,7 @@ static int ops_init(const struct pernet_operations *ops, struct net *net) int err = -ENOMEM; void *data = NULL; - if (ops->id && ops->size) { + if (ops->id) { data = kzalloc(ops->size, GFP_KERNEL); if (!data) goto out; @@ -140,7 +140,7 @@ static int ops_init(const struct pernet_operations *ops, struct net *net) if (!err) return 0; - if (ops->id && ops->size) { + if (ops->id) { ng = rcu_dereference_protected(net->gen, lockdep_is_held(&pernet_ops_rwsem)); ng->ptr[*ops->id] = NULL; @@ -182,7 +182,8 @@ static void ops_free_list(const struct pernet_operations *ops, struct list_head *net_exit_list) { struct net *net; - if (ops->size && ops->id) { + + if (ops->id) { list_for_each_entry(net, net_exit_list, exit_list) kfree(net_generic(net, *ops->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); +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. */ -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"); + + 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. */ -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 */ 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) LIST_HEAD(dev_kill_list); 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(); net->net_cookie = gen_cookie_next(&net_cookie); 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) { error = ops_init(ops, net); @@ -382,32 +395,6 @@ out_undo: 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 static struct ucounts *inc_net_namespaces(struct user_namespace *ns) { @@ -496,8 +483,7 @@ struct net *copy_net_ns(unsigned long flags, goto dec_ucounts; } - preinit_net(net); - refcount_set(&net->passive, 1); + preinit_net(net, user_ns); net->ucounts = ucounts; get_user_ns(user_ns); @@ -505,7 +491,7 @@ struct net *copy_net_ns(unsigned long flags, if (rv < 0) goto put_userns; - rv = setup_net(net, user_ns); + rv = setup_net(net); up_read(&pernet_ops_rwsem); @@ -1199,9 +1185,10 @@ void __init net_ns_init(void) #ifdef CONFIG_KEYS init_net.key_domain = &init_net_key_domain; #endif + preinit_net(&init_net, &init_user_ns); + down_write(&pernet_ops_rwsem); - preinit_net(&init_net); - if (setup_net(&init_net, &init_user_ns)) + if (setup_net(&init_net)) panic("Could not setup the initial network namespace"); init_net_initialized = true; @@ -1244,7 +1231,7 @@ static int __register_pernet_operations(struct list_head *list, LIST_HEAD(net_exit_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 * setup_net() and cleanup_net() are not possible. */ @@ -1310,6 +1297,9 @@ static int register_pernet_operations(struct list_head *list, { int error; + if (WARN_ON(!!ops->id ^ !!ops->size)) + return -EINVAL; + if (ops->id) { error = ida_alloc_min(&net_generic_ids, MIN_PERNET_OPS_ID, GFP_KERNEL); diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 90bf3a8ccab6..9b4273fd518a 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c @@ -1393,8 +1393,6 @@ end: * L2TPv2, we dump only L2TPv2 tunnels and sessions here. *****************************************************************************/ -static unsigned int pppol2tp_net_id; - #ifdef CONFIG_PROC_FS struct pppol2tp_seq_data { @@ -1628,7 +1626,6 @@ static __net_exit void pppol2tp_exit_net(struct net *net) static struct pernet_operations pppol2tp_net_ops = { .init = pppol2tp_init_net, .exit = pppol2tp_exit_net, - .id = &pppol2tp_net_id, }; /***************************************************************************** |