Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 70ee1159 authored by Pavel Emelyanov's avatar Pavel Emelyanov Committed by David S. Miller
Browse files

[SOCK][NETNS]: Add the percpu prot_inuse counter in the struct net.



Such an accounting would cost us two more dereferences to get the
percpu variable from the struct net, so I make sock_prot_inuse_get
and _add calls work differently depending on CONFIG_NET_NS - without
it old optimized routines are used.

The per-cpu counter for init_net is prepared in core_initcall, so
that even af_inet, that starts as fs_initcall, will already have the
init_net prepared.

Signed-off-by: default avatarPavel Emelyanov <xemul@openvz.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c29a0bc4
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -2,12 +2,15 @@
#define __NETNS_CORE_H__
#define __NETNS_CORE_H__


struct ctl_table_header;
struct ctl_table_header;
struct prot_inuse;


struct netns_core {
struct netns_core {
	/* core sysctls */
	/* core sysctls */
	struct ctl_table_header	*sysctl_hdr;
	struct ctl_table_header	*sysctl_hdr;


	int	sysctl_somaxconn;
	int	sysctl_somaxconn;

	struct prot_inuse	*inuse;
};
};


#endif
#endif
+48 −0
Original line number Original line Diff line number Diff line
@@ -1947,6 +1947,53 @@ struct prot_inuse {
};
};


static DECLARE_BITMAP(proto_inuse_idx, PROTO_INUSE_NR);
static DECLARE_BITMAP(proto_inuse_idx, PROTO_INUSE_NR);

#ifdef CONFIG_NET_NS
void sock_prot_inuse_add(struct net *net, struct proto *prot, int val)
{
	int cpu = smp_processor_id();
	per_cpu_ptr(net->core.inuse, cpu)->val[prot->inuse_idx] += val;
}
EXPORT_SYMBOL_GPL(sock_prot_inuse_add);

int sock_prot_inuse_get(struct net *net, struct proto *prot)
{
	int cpu, idx = prot->inuse_idx;
	int res = 0;

	for_each_possible_cpu(cpu)
		res += per_cpu_ptr(net->core.inuse, cpu)->val[idx];

	return res >= 0 ? res : 0;
}
EXPORT_SYMBOL_GPL(sock_prot_inuse_get);

static int sock_inuse_init_net(struct net *net)
{
	net->core.inuse = alloc_percpu(struct prot_inuse);
	return net->core.inuse ? 0 : -ENOMEM;
}

static void sock_inuse_exit_net(struct net *net)
{
	free_percpu(net->core.inuse);
}

static struct pernet_operations net_inuse_ops = {
	.init = sock_inuse_init_net,
	.exit = sock_inuse_exit_net,
};

static __init int net_inuse_init(void)
{
	if (register_pernet_subsys(&net_inuse_ops))
		panic("Cannot initialize net inuse counters");

	return 0;
}

core_initcall(net_inuse_init);
#else
static DEFINE_PER_CPU(struct prot_inuse, prot_inuse);
static DEFINE_PER_CPU(struct prot_inuse, prot_inuse);


void sock_prot_inuse_add(struct net *net, struct proto *prot, int val)
void sock_prot_inuse_add(struct net *net, struct proto *prot, int val)
@@ -1966,6 +2013,7 @@ int sock_prot_inuse_get(struct net *net, struct proto *prot)
	return res >= 0 ? res : 0;
	return res >= 0 ? res : 0;
}
}
EXPORT_SYMBOL_GPL(sock_prot_inuse_get);
EXPORT_SYMBOL_GPL(sock_prot_inuse_get);
#endif


static void assign_proto_idx(struct proto *prot)
static void assign_proto_idx(struct proto *prot)
{
{