[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: Pavel Emelyanov <xemul@openvz.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
c29a0bc4df
commit
70ee115942
2 changed files with 51 additions and 0 deletions
|
@ -2,12 +2,15 @@
|
|||
#define __NETNS_CORE_H__
|
||||
|
||||
struct ctl_table_header;
|
||||
struct prot_inuse;
|
||||
|
||||
struct netns_core {
|
||||
/* core sysctls */
|
||||
struct ctl_table_header *sysctl_hdr;
|
||||
|
||||
int sysctl_somaxconn;
|
||||
|
||||
struct prot_inuse *inuse;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1947,6 +1947,53 @@ struct prot_inuse {
|
|||
};
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sock_prot_inuse_get);
|
||||
#endif
|
||||
|
||||
static void assign_proto_idx(struct proto *prot)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue