Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.25 350 lines 8.1 kB view raw
1#include <linux/workqueue.h> 2#include <linux/rtnetlink.h> 3#include <linux/cache.h> 4#include <linux/slab.h> 5#include <linux/list.h> 6#include <linux/delay.h> 7#include <linux/sched.h> 8#include <net/net_namespace.h> 9 10/* 11 * Our network namespace constructor/destructor lists 12 */ 13 14static LIST_HEAD(pernet_list); 15static struct list_head *first_device = &pernet_list; 16static DEFINE_MUTEX(net_mutex); 17 18LIST_HEAD(net_namespace_list); 19 20struct net init_net; 21EXPORT_SYMBOL(init_net); 22 23/* 24 * setup_net runs the initializers for the network namespace object. 25 */ 26static __net_init int setup_net(struct net *net) 27{ 28 /* Must be called with net_mutex held */ 29 struct pernet_operations *ops; 30 int error; 31 32 atomic_set(&net->count, 1); 33 atomic_set(&net->use_count, 0); 34 35 error = 0; 36 list_for_each_entry(ops, &pernet_list, list) { 37 if (ops->init) { 38 error = ops->init(net); 39 if (error < 0) 40 goto out_undo; 41 } 42 } 43out: 44 return error; 45 46out_undo: 47 /* Walk through the list backwards calling the exit functions 48 * for the pernet modules whose init functions did not fail. 49 */ 50 list_for_each_entry_continue_reverse(ops, &pernet_list, list) { 51 if (ops->exit) 52 ops->exit(net); 53 } 54 55 rcu_barrier(); 56 goto out; 57} 58 59#ifdef CONFIG_NET_NS 60static struct kmem_cache *net_cachep; 61static struct workqueue_struct *netns_wq; 62 63static struct net *net_alloc(void) 64{ 65 return kmem_cache_zalloc(net_cachep, GFP_KERNEL); 66} 67 68static void net_free(struct net *net) 69{ 70 if (!net) 71 return; 72 73 if (unlikely(atomic_read(&net->use_count) != 0)) { 74 printk(KERN_EMERG "network namespace not free! Usage: %d\n", 75 atomic_read(&net->use_count)); 76 return; 77 } 78 79 kmem_cache_free(net_cachep, net); 80} 81 82struct net *copy_net_ns(unsigned long flags, struct net *old_net) 83{ 84 struct net *new_net = NULL; 85 int err; 86 87 get_net(old_net); 88 89 if (!(flags & CLONE_NEWNET)) 90 return old_net; 91 92 err = -ENOMEM; 93 new_net = net_alloc(); 94 if (!new_net) 95 goto out; 96 97 mutex_lock(&net_mutex); 98 err = setup_net(new_net); 99 if (err) 100 goto out_unlock; 101 102 rtnl_lock(); 103 list_add_tail(&new_net->list, &net_namespace_list); 104 rtnl_unlock(); 105 106 107out_unlock: 108 mutex_unlock(&net_mutex); 109out: 110 put_net(old_net); 111 if (err) { 112 net_free(new_net); 113 new_net = ERR_PTR(err); 114 } 115 return new_net; 116} 117 118static void cleanup_net(struct work_struct *work) 119{ 120 struct pernet_operations *ops; 121 struct net *net; 122 123 net = container_of(work, struct net, work); 124 125 mutex_lock(&net_mutex); 126 127 /* Don't let anyone else find us. */ 128 rtnl_lock(); 129 list_del(&net->list); 130 rtnl_unlock(); 131 132 /* Run all of the network namespace exit methods */ 133 list_for_each_entry_reverse(ops, &pernet_list, list) { 134 if (ops->exit) 135 ops->exit(net); 136 } 137 138 mutex_unlock(&net_mutex); 139 140 /* Ensure there are no outstanding rcu callbacks using this 141 * network namespace. 142 */ 143 rcu_barrier(); 144 145 /* Finally it is safe to free my network namespace structure */ 146 net_free(net); 147} 148 149void __put_net(struct net *net) 150{ 151 /* Cleanup the network namespace in process context */ 152 INIT_WORK(&net->work, cleanup_net); 153 queue_work(netns_wq, &net->work); 154} 155EXPORT_SYMBOL_GPL(__put_net); 156 157#else 158struct net *copy_net_ns(unsigned long flags, struct net *old_net) 159{ 160 if (flags & CLONE_NEWNET) 161 return ERR_PTR(-EINVAL); 162 return old_net; 163} 164#endif 165 166static int __init net_ns_init(void) 167{ 168 int err; 169 170 printk(KERN_INFO "net_namespace: %zd bytes\n", sizeof(struct net)); 171#ifdef CONFIG_NET_NS 172 net_cachep = kmem_cache_create("net_namespace", sizeof(struct net), 173 SMP_CACHE_BYTES, 174 SLAB_PANIC, NULL); 175 176 /* Create workqueue for cleanup */ 177 netns_wq = create_singlethread_workqueue("netns"); 178 if (!netns_wq) 179 panic("Could not create netns workq"); 180#endif 181 182 mutex_lock(&net_mutex); 183 err = setup_net(&init_net); 184 185 rtnl_lock(); 186 list_add_tail(&init_net.list, &net_namespace_list); 187 rtnl_unlock(); 188 189 mutex_unlock(&net_mutex); 190 if (err) 191 panic("Could not setup the initial network namespace"); 192 193 return 0; 194} 195 196pure_initcall(net_ns_init); 197 198#ifdef CONFIG_NET_NS 199static int register_pernet_operations(struct list_head *list, 200 struct pernet_operations *ops) 201{ 202 struct net *net, *undo_net; 203 int error; 204 205 list_add_tail(&ops->list, list); 206 if (ops->init) { 207 for_each_net(net) { 208 error = ops->init(net); 209 if (error) 210 goto out_undo; 211 } 212 } 213 return 0; 214 215out_undo: 216 /* If I have an error cleanup all namespaces I initialized */ 217 list_del(&ops->list); 218 if (ops->exit) { 219 for_each_net(undo_net) { 220 if (undo_net == net) 221 goto undone; 222 ops->exit(undo_net); 223 } 224 } 225undone: 226 return error; 227} 228 229static void unregister_pernet_operations(struct pernet_operations *ops) 230{ 231 struct net *net; 232 233 list_del(&ops->list); 234 if (ops->exit) 235 for_each_net(net) 236 ops->exit(net); 237} 238 239#else 240 241static int register_pernet_operations(struct list_head *list, 242 struct pernet_operations *ops) 243{ 244 if (ops->init == NULL) 245 return 0; 246 return ops->init(&init_net); 247} 248 249static void unregister_pernet_operations(struct pernet_operations *ops) 250{ 251 if (ops->exit) 252 ops->exit(&init_net); 253} 254#endif 255 256/** 257 * register_pernet_subsys - register a network namespace subsystem 258 * @ops: pernet operations structure for the subsystem 259 * 260 * Register a subsystem which has init and exit functions 261 * that are called when network namespaces are created and 262 * destroyed respectively. 263 * 264 * When registered all network namespace init functions are 265 * called for every existing network namespace. Allowing kernel 266 * modules to have a race free view of the set of network namespaces. 267 * 268 * When a new network namespace is created all of the init 269 * methods are called in the order in which they were registered. 270 * 271 * When a network namespace is destroyed all of the exit methods 272 * are called in the reverse of the order with which they were 273 * registered. 274 */ 275int register_pernet_subsys(struct pernet_operations *ops) 276{ 277 int error; 278 mutex_lock(&net_mutex); 279 error = register_pernet_operations(first_device, ops); 280 mutex_unlock(&net_mutex); 281 return error; 282} 283EXPORT_SYMBOL_GPL(register_pernet_subsys); 284 285/** 286 * unregister_pernet_subsys - unregister a network namespace subsystem 287 * @ops: pernet operations structure to manipulate 288 * 289 * Remove the pernet operations structure from the list to be 290 * used when network namespaces are created or destroyed. In 291 * addition run the exit method for all existing network 292 * namespaces. 293 */ 294void unregister_pernet_subsys(struct pernet_operations *module) 295{ 296 mutex_lock(&net_mutex); 297 unregister_pernet_operations(module); 298 mutex_unlock(&net_mutex); 299} 300EXPORT_SYMBOL_GPL(unregister_pernet_subsys); 301 302/** 303 * register_pernet_device - register a network namespace device 304 * @ops: pernet operations structure for the subsystem 305 * 306 * Register a device which has init and exit functions 307 * that are called when network namespaces are created and 308 * destroyed respectively. 309 * 310 * When registered all network namespace init functions are 311 * called for every existing network namespace. Allowing kernel 312 * modules to have a race free view of the set of network namespaces. 313 * 314 * When a new network namespace is created all of the init 315 * methods are called in the order in which they were registered. 316 * 317 * When a network namespace is destroyed all of the exit methods 318 * are called in the reverse of the order with which they were 319 * registered. 320 */ 321int register_pernet_device(struct pernet_operations *ops) 322{ 323 int error; 324 mutex_lock(&net_mutex); 325 error = register_pernet_operations(&pernet_list, ops); 326 if (!error && (first_device == &pernet_list)) 327 first_device = &ops->list; 328 mutex_unlock(&net_mutex); 329 return error; 330} 331EXPORT_SYMBOL_GPL(register_pernet_device); 332 333/** 334 * unregister_pernet_device - unregister a network namespace netdevice 335 * @ops: pernet operations structure to manipulate 336 * 337 * Remove the pernet operations structure from the list to be 338 * used when network namespaces are created or destroyed. In 339 * addition run the exit method for all existing network 340 * namespaces. 341 */ 342void unregister_pernet_device(struct pernet_operations *ops) 343{ 344 mutex_lock(&net_mutex); 345 if (&ops->list == first_device) 346 first_device = first_device->next; 347 unregister_pernet_operations(ops); 348 mutex_unlock(&net_mutex); 349} 350EXPORT_SYMBOL_GPL(unregister_pernet_device);