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

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
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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;
};

/*
+37 −47
Original line number Diff line number Diff line
@@ -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);
+0 −3
Original line number Diff line number Diff line
@@ -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,
};

/*****************************************************************************