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 {
/* 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;
};
/*
......
......@@ -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 @@ static __net_init int setup_net(struct net *net, struct user_namespace *user_ns)
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);
......
......@@ -1393,8 +1393,6 @@ static int pppol2tp_getsockopt(struct socket *sock, int level, int optname,
* 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,
};
/*****************************************************************************
......
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