Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 172035
b: refs/heads/master
c: 2b035b3
h: refs/heads/master
i:
  172033: 0f63def
  172031: 34ad129
v: v3
  • Loading branch information
Eric W. Biederman authored and David S. Miller committed Dec 2, 2009
1 parent a82c6dc commit 871c678
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 10 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: dcbccbd4f1f6ad0f0e169d4b2e816e42bde06f82
refs/heads/master: 2b035b39970740722598f7a9d548835f9bdd730f
2 changes: 1 addition & 1 deletion trunk/include/net/net_namespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ struct net {
*/
#endif
struct list_head list; /* list of network namespaces */
struct work_struct work; /* work struct for freeing */
struct list_head cleanup_list; /* namespaces on death row */

struct proc_dir_entry *proc_net;
struct proc_dir_entry *proc_net_stat;
Expand Down
66 changes: 58 additions & 8 deletions trunk/net/core/net_namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
#include <linux/idr.h>
#include <linux/rculist.h>
#include <linux/nsproxy.h>
#include <linux/netdevice.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
#include <net/rtnetlink.h>

/*
* Our network namespace constructor/destructor lists
Expand All @@ -27,6 +29,20 @@ EXPORT_SYMBOL(init_net);

#define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */

static void unregister_netdevices(struct net *net, struct list_head *list)
{
struct net_device *dev;
/* At exit all network devices most be removed from a network
* namespace. Do this in the reverse order of registeration.
*/
for_each_netdev_reverse(net, dev) {
if (dev->rtnl_link_ops)
dev->rtnl_link_ops->dellink(dev, list);
else
unregister_netdevice_queue(dev, list);
}
}

/*
* setup_net runs the initializers for the network namespace object.
*/
Expand Down Expand Up @@ -59,6 +75,13 @@ static __net_init int setup_net(struct net *net)
list_for_each_entry_continue_reverse(ops, &pernet_list, list) {
if (ops->exit)
ops->exit(net);
if (&ops->list == first_device) {
LIST_HEAD(dev_kill_list);
rtnl_lock();
unregister_netdevices(net, &dev_kill_list);
unregister_netdevice_many(&dev_kill_list);
rtnl_unlock();
}
}

rcu_barrier();
Expand Down Expand Up @@ -147,18 +170,26 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net)
return net_create();
}

static DEFINE_SPINLOCK(cleanup_list_lock);
static LIST_HEAD(cleanup_list); /* Must hold cleanup_list_lock to touch */

static void cleanup_net(struct work_struct *work)
{
struct pernet_operations *ops;
struct net *net;
struct net *net, *tmp;
LIST_HEAD(net_kill_list);

net = container_of(work, struct net, work);
/* Atomically snapshot the list of namespaces to cleanup */
spin_lock_irq(&cleanup_list_lock);
list_replace_init(&cleanup_list, &net_kill_list);
spin_unlock_irq(&cleanup_list_lock);

mutex_lock(&net_mutex);

/* Don't let anyone else find us. */
rtnl_lock();
list_del_rcu(&net->list);
list_for_each_entry(net, &net_kill_list, cleanup_list)
list_del_rcu(&net->list);
rtnl_unlock();

/*
Expand All @@ -170,8 +201,18 @@ static void cleanup_net(struct work_struct *work)

/* Run all of the network namespace exit methods */
list_for_each_entry_reverse(ops, &pernet_list, list) {
if (ops->exit)
ops->exit(net);
if (ops->exit) {
list_for_each_entry(net, &net_kill_list, cleanup_list)
ops->exit(net);
}
if (&ops->list == first_device) {
LIST_HEAD(dev_kill_list);
rtnl_lock();
list_for_each_entry(net, &net_kill_list, cleanup_list)
unregister_netdevices(net, &dev_kill_list);
unregister_netdevice_many(&dev_kill_list);
rtnl_unlock();
}
}

mutex_unlock(&net_mutex);
Expand All @@ -182,14 +223,23 @@ static void cleanup_net(struct work_struct *work)
rcu_barrier();

/* Finally it is safe to free my network namespace structure */
net_free(net);
list_for_each_entry_safe(net, tmp, &net_kill_list, cleanup_list) {
list_del_init(&net->cleanup_list);
net_free(net);
}
}
static DECLARE_WORK(net_cleanup_work, cleanup_net);

void __put_net(struct net *net)
{
/* Cleanup the network namespace in process context */
INIT_WORK(&net->work, cleanup_net);
queue_work(netns_wq, &net->work);
unsigned long flags;

spin_lock_irqsave(&cleanup_list_lock, flags);
list_add(&net->cleanup_list, &cleanup_list);
spin_unlock_irqrestore(&cleanup_list_lock, flags);

queue_work(netns_wq, &net_cleanup_work);
}
EXPORT_SYMBOL_GPL(__put_net);

Expand Down

0 comments on commit 871c678

Please sign in to comment.