Commit 17edde52 authored by Eric W. Biederman's avatar Eric W. Biederman Committed by David S. Miller

netns: Remove net_alive

It turns out that net_alive is unnecessary, and the original problem
that led to it being added was simply that the icmp code thought
it was a network device and wound up being unable to handle packets
while there were still packets in the network namespace.

Now that icmp and tcp have been fixed to properly register themselves
this problem is no longer present and we have a stronger guarantee
that packets will not arrive in a network namespace then that provided
by net_alive in netif_receive_skb.  So remove net_alive allowing
packet reception run a little faster.

Additionally document the strong reason why network namespace cleanup
is safe so that if something happens again someone else will have
a chance of figuring it out.
Signed-off-by: default avatarEric W. Biederman <ebiederm@aristanetworks.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2f20d2e6
...@@ -109,11 +109,6 @@ extern struct list_head net_namespace_list; ...@@ -109,11 +109,6 @@ extern struct list_head net_namespace_list;
#ifdef CONFIG_NET_NS #ifdef CONFIG_NET_NS
extern void __put_net(struct net *net); extern void __put_net(struct net *net);
static inline int net_alive(struct net *net)
{
return net && atomic_read(&net->count);
}
static inline struct net *get_net(struct net *net) static inline struct net *get_net(struct net *net)
{ {
atomic_inc(&net->count); atomic_inc(&net->count);
...@@ -145,11 +140,6 @@ int net_eq(const struct net *net1, const struct net *net2) ...@@ -145,11 +140,6 @@ int net_eq(const struct net *net1, const struct net *net2)
} }
#else #else
static inline int net_alive(struct net *net)
{
return 1;
}
static inline struct net *get_net(struct net *net) static inline struct net *get_net(struct net *net)
{ {
return net; return net;
...@@ -234,6 +224,23 @@ struct pernet_operations { ...@@ -234,6 +224,23 @@ struct pernet_operations {
void (*exit)(struct net *net); void (*exit)(struct net *net);
}; };
/*
* Use these carefully. If you implement a network device and it
* needs per network namespace operations use device pernet operations,
* otherwise use pernet subsys operations.
*
* This is critically important. Most of the network code cleanup
* runs with the assumption that dev_remove_pack has been called so no
* new packets will arrive during and after the cleanup functions have
* been called. dev_remove_pack is not per namespace so instead the
* guarantee of no more packets arriving in a network namespace is
* provided by ensuring that all network devices and all sockets have
* left the network namespace before the cleanup methods are called.
*
* For the longest time the ipv4 icmp code was registered as a pernet
* device which caused kernel oops, and panics during network
* namespace cleanup. So please don't get this wrong.
*/
extern int register_pernet_subsys(struct pernet_operations *); extern int register_pernet_subsys(struct pernet_operations *);
extern void unregister_pernet_subsys(struct pernet_operations *); extern void unregister_pernet_subsys(struct pernet_operations *);
extern int register_pernet_gen_subsys(int *id, struct pernet_operations *); extern int register_pernet_gen_subsys(int *id, struct pernet_operations *);
......
...@@ -2267,12 +2267,6 @@ int netif_receive_skb(struct sk_buff *skb) ...@@ -2267,12 +2267,6 @@ int netif_receive_skb(struct sk_buff *skb)
rcu_read_lock(); rcu_read_lock();
/* Don't receive packets in an exiting network namespace */
if (!net_alive(dev_net(skb->dev))) {
kfree_skb(skb);
goto out;
}
#ifdef CONFIG_NET_CLS_ACT #ifdef CONFIG_NET_CLS_ACT
if (skb->tc_verd & TC_NCLS) { if (skb->tc_verd & TC_NCLS) {
skb->tc_verd = CLR_TC_NCLS(skb->tc_verd); skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
......
...@@ -157,9 +157,6 @@ static void cleanup_net(struct work_struct *work) ...@@ -157,9 +157,6 @@ static void cleanup_net(struct work_struct *work)
struct pernet_operations *ops; struct pernet_operations *ops;
struct net *net; struct net *net;
/* Be very certain incoming network packets will not find us */
rcu_barrier();
net = container_of(work, struct net, work); net = container_of(work, struct net, work);
mutex_lock(&net_mutex); mutex_lock(&net_mutex);
......
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