Blame view
net/core/net_namespace.c
14.4 KB
5f256becd [NET]: Basic netw... |
1 2 3 4 5 6 |
#include <linux/workqueue.h> #include <linux/rtnetlink.h> #include <linux/cache.h> #include <linux/slab.h> #include <linux/list.h> #include <linux/delay.h> |
9dd776b6d [NET]: Add networ... |
7 |
#include <linux/sched.h> |
c93cf61fd [NETNS]: The net-... |
8 |
#include <linux/idr.h> |
11a28d373 net: make namespa... |
9 |
#include <linux/rculist.h> |
30ffee848 net: move and exp... |
10 |
#include <linux/nsproxy.h> |
f06305294 net: Allow settin... |
11 12 |
#include <linux/proc_fs.h> #include <linux/file.h> |
bc3b2d7fb net: Add export.h... |
13 |
#include <linux/export.h> |
5f256becd [NET]: Basic netw... |
14 |
#include <net/net_namespace.h> |
dec827d17 [NETNS]: The gene... |
15 |
#include <net/netns/generic.h> |
5f256becd [NET]: Basic netw... |
16 17 18 19 20 21 22 23 |
/* * Our network namespace constructor/destructor lists */ static LIST_HEAD(pernet_list); static struct list_head *first_device = &pernet_list; static DEFINE_MUTEX(net_mutex); |
5f256becd [NET]: Basic netw... |
24 |
LIST_HEAD(net_namespace_list); |
b76a461f1 netns: export net... |
25 |
EXPORT_SYMBOL_GPL(net_namespace_list); |
5f256becd [NET]: Basic netw... |
26 |
|
5f256becd [NET]: Basic netw... |
27 |
struct net init_net; |
ff4b95027 [NETNS]: Re-expor... |
28 |
EXPORT_SYMBOL(init_net); |
5f256becd [NET]: Basic netw... |
29 |
|
dec827d17 [NETNS]: The gene... |
30 |
#define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */ |
05fceb4ad net: disallow to ... |
31 32 33 34 35 36 |
static int net_assign_generic(struct net *net, int id, void *data) { struct net_generic *ng, *old_ng; BUG_ON(!mutex_is_locked(&net_mutex)); BUG_ON(id == 0); |
1c87733d0 net_ns: add __rcu... |
37 38 39 |
old_ng = rcu_dereference_protected(net->gen, lockdep_is_held(&net_mutex)); ng = old_ng; |
05fceb4ad net: disallow to ... |
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
if (old_ng->len >= id) goto assign; ng = kzalloc(sizeof(struct net_generic) + id * sizeof(void *), GFP_KERNEL); if (ng == NULL) return -ENOMEM; /* * Some synchronisation notes: * * The net_generic explores the net->gen array inside rcu * read section. Besides once set the net->gen->ptr[x] * pointer never changes (see rules in netns/generic.h). * * That said, we simply duplicate this array and schedule * the old copy for kfree after a grace period. */ ng->len = id; memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*)); rcu_assign_pointer(net->gen, ng); |
04d4dfed8 net,rcu: convert ... |
63 |
kfree_rcu(old_ng, rcu); |
05fceb4ad net: disallow to ... |
64 65 66 67 |
assign: ng->ptr[id - 1] = data; return 0; } |
f875bae06 net: Automaticall... |
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
static int ops_init(const struct pernet_operations *ops, struct net *net) { int err; if (ops->id && ops->size) { void *data = kzalloc(ops->size, GFP_KERNEL); if (!data) return -ENOMEM; err = net_assign_generic(net, *ops->id, data); if (err) { kfree(data); return err; } } if (ops->init) return ops->init(net); return 0; } static void ops_free(const struct pernet_operations *ops, struct net *net) { if (ops->id && ops->size) { int id = *ops->id; kfree(net_generic(net, id)); } } |
72ad937ab net: Add support ... |
94 95 96 97 98 99 100 101 |
static void ops_exit_list(const struct pernet_operations *ops, struct list_head *net_exit_list) { struct net *net; if (ops->exit) { list_for_each_entry(net, net_exit_list, exit_list) ops->exit(net); } |
72ad937ab net: Add support ... |
102 103 104 105 106 107 108 109 110 111 112 113 114 |
if (ops->exit_batch) ops->exit_batch(net_exit_list); } static void ops_free_list(const struct pernet_operations *ops, struct list_head *net_exit_list) { struct net *net; if (ops->size && ops->id) { list_for_each_entry(net, net_exit_list, exit_list) ops_free(ops, net); } } |
5f256becd [NET]: Basic netw... |
115 116 117 |
/* * setup_net runs the initializers for the network namespace object. */ |
1a2ee93d2 [NET]: Mark the s... |
118 |
static __net_init int setup_net(struct net *net) |
5f256becd [NET]: Basic netw... |
119 120 |
{ /* Must be called with net_mutex held */ |
f875bae06 net: Automaticall... |
121 |
const struct pernet_operations *ops, *saved_ops; |
486a87f1e netns: fix double... |
122 |
int error = 0; |
72ad937ab net: Add support ... |
123 |
LIST_HEAD(net_exit_list); |
5f256becd [NET]: Basic netw... |
124 |
|
5f256becd [NET]: Basic netw... |
125 |
atomic_set(&net->count, 1); |
a685e0898 Delay struct net ... |
126 |
atomic_set(&net->passive, 1); |
4e985adaa rtnl: provide lin... |
127 |
net->dev_base_seq = 1; |
486a87f1e netns: fix double... |
128 |
|
5d1e4468a [NETNS]: Make net... |
129 |
#ifdef NETNS_REFCNT_DEBUG |
5f256becd [NET]: Basic netw... |
130 |
atomic_set(&net->use_count, 0); |
5d1e4468a [NETNS]: Make net... |
131 |
#endif |
5f256becd [NET]: Basic netw... |
132 |
|
768f3591e [NETNS]: Cleanup ... |
133 |
list_for_each_entry(ops, &pernet_list, list) { |
f875bae06 net: Automaticall... |
134 135 136 |
error = ops_init(ops, net); if (error < 0) goto out_undo; |
5f256becd [NET]: Basic netw... |
137 138 139 |
} out: return error; |
768f3591e [NETNS]: Cleanup ... |
140 |
|
5f256becd [NET]: Basic netw... |
141 142 143 144 |
out_undo: /* Walk through the list backwards calling the exit functions * for the pernet modules whose init functions did not fail. */ |
72ad937ab net: Add support ... |
145 |
list_add(&net->exit_list, &net_exit_list); |
f875bae06 net: Automaticall... |
146 |
saved_ops = ops; |
72ad937ab net: Add support ... |
147 148 |
list_for_each_entry_continue_reverse(ops, &pernet_list, list) ops_exit_list(ops, &net_exit_list); |
f875bae06 net: Automaticall... |
149 150 |
ops = saved_ops; list_for_each_entry_continue_reverse(ops, &pernet_list, list) |
72ad937ab net: Add support ... |
151 |
ops_free_list(ops, &net_exit_list); |
310928d96 [NETNS]: fix net ... |
152 153 |
rcu_barrier(); |
5f256becd [NET]: Basic netw... |
154 155 |
goto out; } |
486a87f1e netns: fix double... |
156 |
static struct net_generic *net_alloc_generic(void) |
6a1a3b9f6 [NET]: Hide the d... |
157 |
{ |
486a87f1e netns: fix double... |
158 159 160 161 162 163 164 165 166 |
struct net_generic *ng; size_t generic_size = sizeof(struct net_generic) + INITIAL_NET_GEN_PTRS * sizeof(void *); ng = kzalloc(generic_size, GFP_KERNEL); if (ng) ng->len = INITIAL_NET_GEN_PTRS; return ng; |
6a1a3b9f6 [NET]: Hide the d... |
167 |
} |
ebe47d47b netns: build fix ... |
168 169 170 |
#ifdef CONFIG_NET_NS static struct kmem_cache *net_cachep; static struct workqueue_struct *netns_wq; |
486a87f1e netns: fix double... |
171 |
static struct net *net_alloc(void) |
45a19b0a7 [NETNS]: Fix comp... |
172 |
{ |
486a87f1e netns: fix double... |
173 174 175 176 177 178 179 180 |
struct net *net = NULL; struct net_generic *ng; ng = net_alloc_generic(); if (!ng) goto out; net = kmem_cache_zalloc(net_cachep, GFP_KERNEL); |
45a19b0a7 [NETNS]: Fix comp... |
181 |
if (!net) |
486a87f1e netns: fix double... |
182 |
goto out_free; |
45a19b0a7 [NETNS]: Fix comp... |
183 |
|
486a87f1e netns: fix double... |
184 185 186 187 188 189 190 191 192 193 194 |
rcu_assign_pointer(net->gen, ng); out: return net; out_free: kfree(ng); goto out; } static void net_free(struct net *net) { |
5d1e4468a [NETNS]: Make net... |
195 |
#ifdef NETNS_REFCNT_DEBUG |
45a19b0a7 [NETNS]: Fix comp... |
196 197 198 199 200 201 |
if (unlikely(atomic_read(&net->use_count) != 0)) { printk(KERN_EMERG "network namespace not free! Usage: %d ", atomic_read(&net->use_count)); return; } |
5d1e4468a [NETNS]: Make net... |
202 |
#endif |
4ef079ccc netns: fix net_ge... |
203 |
kfree(net->gen); |
45a19b0a7 [NETNS]: Fix comp... |
204 205 |
kmem_cache_free(net_cachep, net); } |
a685e0898 Delay struct net ... |
206 207 208 209 210 211 |
void net_drop_ns(void *p) { struct net *ns = p; if (ns && atomic_dec_and_test(&ns->passive)) net_free(ns); } |
911cb193f net: minor cleanu... |
212 |
struct net *copy_net_ns(unsigned long flags, struct net *old_net) |
9dd776b6d [NET]: Add networ... |
213 |
{ |
088eb2d90 netns 2/2: extrac... |
214 215 |
struct net *net; int rv; |
9dd776b6d [NET]: Add networ... |
216 |
|
911cb193f net: minor cleanu... |
217 218 |
if (!(flags & CLONE_NEWNET)) return get_net(old_net); |
088eb2d90 netns 2/2: extrac... |
219 220 221 |
net = net_alloc(); if (!net) return ERR_PTR(-ENOMEM); |
9dd776b6d [NET]: Add networ... |
222 |
mutex_lock(&net_mutex); |
088eb2d90 netns 2/2: extrac... |
223 224 |
rv = setup_net(net); if (rv == 0) { |
486a87f1e netns: fix double... |
225 |
rtnl_lock(); |
11a28d373 net: make namespa... |
226 |
list_add_tail_rcu(&net->list, &net_namespace_list); |
486a87f1e netns: fix double... |
227 228 |
rtnl_unlock(); } |
9dd776b6d [NET]: Add networ... |
229 |
mutex_unlock(&net_mutex); |
088eb2d90 netns 2/2: extrac... |
230 |
if (rv < 0) { |
a685e0898 Delay struct net ... |
231 |
net_drop_ns(net); |
088eb2d90 netns 2/2: extrac... |
232 233 234 235 |
return ERR_PTR(rv); } return net; } |
486a87f1e netns: fix double... |
236 |
|
2b035b399 net: Batch networ... |
237 238 |
static DEFINE_SPINLOCK(cleanup_list_lock); static LIST_HEAD(cleanup_list); /* Must hold cleanup_list_lock to touch */ |
6a1a3b9f6 [NET]: Hide the d... |
239 240 |
static void cleanup_net(struct work_struct *work) { |
f875bae06 net: Automaticall... |
241 |
const struct pernet_operations *ops; |
2b035b399 net: Batch networ... |
242 243 |
struct net *net, *tmp; LIST_HEAD(net_kill_list); |
72ad937ab net: Add support ... |
244 |
LIST_HEAD(net_exit_list); |
6a1a3b9f6 [NET]: Hide the d... |
245 |
|
2b035b399 net: Batch networ... |
246 247 248 249 |
/* 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); |
6a1a3b9f6 [NET]: Hide the d... |
250 251 252 253 254 |
mutex_lock(&net_mutex); /* Don't let anyone else find us. */ rtnl_lock(); |
72ad937ab net: Add support ... |
255 |
list_for_each_entry(net, &net_kill_list, cleanup_list) { |
2b035b399 net: Batch networ... |
256 |
list_del_rcu(&net->list); |
72ad937ab net: Add support ... |
257 258 |
list_add_tail(&net->exit_list, &net_exit_list); } |
6a1a3b9f6 [NET]: Hide the d... |
259 |
rtnl_unlock(); |
11a28d373 net: make namespa... |
260 261 262 263 264 265 |
/* * Another CPU might be rcu-iterating the list, wait for it. * This needs to be before calling the exit() notifiers, so * the rcu_barrier() below isn't sufficient alone. */ synchronize_rcu(); |
6a1a3b9f6 [NET]: Hide the d... |
266 |
/* Run all of the network namespace exit methods */ |
72ad937ab net: Add support ... |
267 268 |
list_for_each_entry_reverse(ops, &pernet_list, list) ops_exit_list(ops, &net_exit_list); |
f875bae06 net: Automaticall... |
269 |
/* Free the net generic variables */ |
72ad937ab net: Add support ... |
270 271 |
list_for_each_entry_reverse(ops, &pernet_list, list) ops_free_list(ops, &net_exit_list); |
6a1a3b9f6 [NET]: Hide the d... |
272 273 274 275 276 277 278 279 280 |
mutex_unlock(&net_mutex); /* Ensure there are no outstanding rcu callbacks using this * network namespace. */ rcu_barrier(); /* Finally it is safe to free my network namespace structure */ |
72ad937ab net: Add support ... |
281 282 |
list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) { list_del_init(&net->exit_list); |
a685e0898 Delay struct net ... |
283 |
net_drop_ns(net); |
2b035b399 net: Batch networ... |
284 |
} |
6a1a3b9f6 [NET]: Hide the d... |
285 |
} |
2b035b399 net: Batch networ... |
286 |
static DECLARE_WORK(net_cleanup_work, cleanup_net); |
6a1a3b9f6 [NET]: Hide the d... |
287 288 289 290 |
void __put_net(struct net *net) { /* Cleanup the network namespace in process context */ |
2b035b399 net: Batch networ... |
291 292 293 294 295 296 297 |
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); |
6a1a3b9f6 [NET]: Hide the d... |
298 299 |
} EXPORT_SYMBOL_GPL(__put_net); |
956c92078 net: fix get_net_... |
300 301 302 303 304 |
struct net *get_net_ns_by_fd(int fd) { struct proc_inode *ei; struct file *file; struct net *net; |
956c92078 net: fix get_net_... |
305 |
file = proc_ns_fget(fd); |
c316e6a30 get_net_ns_by_fd(... |
306 307 |
if (IS_ERR(file)) return ERR_CAST(file); |
956c92078 net: fix get_net_... |
308 309 |
ei = PROC_I(file->f_dentry->d_inode); |
c316e6a30 get_net_ns_by_fd(... |
310 311 312 313 |
if (ei->ns_ops == &netns_operations) net = get_net(ei->ns); else net = ERR_PTR(-EINVAL); |
956c92078 net: fix get_net_... |
314 |
|
c316e6a30 get_net_ns_by_fd(... |
315 |
fput(file); |
956c92078 net: fix get_net_... |
316 317 |
return net; } |
6a1a3b9f6 [NET]: Hide the d... |
318 319 320 321 322 323 324 |
#else struct net *copy_net_ns(unsigned long flags, struct net *old_net) { if (flags & CLONE_NEWNET) return ERR_PTR(-EINVAL); return old_net; } |
956c92078 net: fix get_net_... |
325 326 327 328 329 |
struct net *get_net_ns_by_fd(int fd) { return ERR_PTR(-EINVAL); } |
6a1a3b9f6 [NET]: Hide the d... |
330 |
#endif |
30ffee848 net: move and exp... |
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 |
struct net *get_net_ns_by_pid(pid_t pid) { struct task_struct *tsk; struct net *net; /* Lookup the network namespace */ net = ERR_PTR(-ESRCH); rcu_read_lock(); tsk = find_task_by_vpid(pid); if (tsk) { struct nsproxy *nsproxy; nsproxy = task_nsproxy(tsk); if (nsproxy) net = get_net(nsproxy->net_ns); } rcu_read_unlock(); return net; } EXPORT_SYMBOL_GPL(get_net_ns_by_pid); |
5f256becd [NET]: Basic netw... |
350 351 |
static int __init net_ns_init(void) { |
486a87f1e netns: fix double... |
352 |
struct net_generic *ng; |
5f256becd [NET]: Basic netw... |
353 |
|
d57a9212e [NET]: Hide the n... |
354 |
#ifdef CONFIG_NET_NS |
5f256becd [NET]: Basic netw... |
355 356 357 |
net_cachep = kmem_cache_create("net_namespace", sizeof(struct net), SMP_CACHE_BYTES, SLAB_PANIC, NULL); |
3ef1355dc [NET]: Make netns... |
358 359 360 361 362 |
/* Create workqueue for cleanup */ netns_wq = create_singlethread_workqueue("netns"); if (!netns_wq) panic("Could not create netns workq"); |
d57a9212e [NET]: Hide the n... |
363 |
#endif |
3ef1355dc [NET]: Make netns... |
364 |
|
486a87f1e netns: fix double... |
365 366 367 368 369 |
ng = net_alloc_generic(); if (!ng) panic("Could not allocate generic netns"); rcu_assign_pointer(init_net.gen, ng); |
5f256becd [NET]: Basic netw... |
370 |
mutex_lock(&net_mutex); |
ca0f31125 netns: simplify n... |
371 372 |
if (setup_net(&init_net)) panic("Could not setup the initial network namespace"); |
5f256becd [NET]: Basic netw... |
373 |
|
f4618d39a [NETNS]: Simplify... |
374 |
rtnl_lock(); |
11a28d373 net: make namespa... |
375 |
list_add_tail_rcu(&init_net.list, &net_namespace_list); |
f4618d39a [NETNS]: Simplify... |
376 |
rtnl_unlock(); |
5f256becd [NET]: Basic netw... |
377 378 |
mutex_unlock(&net_mutex); |
5f256becd [NET]: Basic netw... |
379 380 381 382 383 |
return 0; } pure_initcall(net_ns_init); |
ed160e839 [NET]: Cleanup pe... |
384 |
#ifdef CONFIG_NET_NS |
f875bae06 net: Automaticall... |
385 386 |
static int __register_pernet_operations(struct list_head *list, struct pernet_operations *ops) |
5f256becd [NET]: Basic netw... |
387 |
{ |
72ad937ab net: Add support ... |
388 |
struct net *net; |
5f256becd [NET]: Basic netw... |
389 |
int error; |
72ad937ab net: Add support ... |
390 |
LIST_HEAD(net_exit_list); |
5f256becd [NET]: Basic netw... |
391 |
|
5f256becd [NET]: Basic netw... |
392 |
list_add_tail(&ops->list, list); |
f875bae06 net: Automaticall... |
393 |
if (ops->init || (ops->id && ops->size)) { |
1dba323b3 [NETNS]: Make the... |
394 |
for_each_net(net) { |
f875bae06 net: Automaticall... |
395 |
error = ops_init(ops, net); |
5f256becd [NET]: Basic netw... |
396 397 |
if (error) goto out_undo; |
72ad937ab net: Add support ... |
398 |
list_add_tail(&net->exit_list, &net_exit_list); |
5f256becd [NET]: Basic netw... |
399 400 |
} } |
1dba323b3 [NETNS]: Make the... |
401 |
return 0; |
5f256becd [NET]: Basic netw... |
402 403 404 405 |
out_undo: /* If I have an error cleanup all namespaces I initialized */ list_del(&ops->list); |
72ad937ab net: Add support ... |
406 407 |
ops_exit_list(ops, &net_exit_list); ops_free_list(ops, &net_exit_list); |
1dba323b3 [NETNS]: Make the... |
408 |
return error; |
5f256becd [NET]: Basic netw... |
409 |
} |
f875bae06 net: Automaticall... |
410 |
static void __unregister_pernet_operations(struct pernet_operations *ops) |
5f256becd [NET]: Basic netw... |
411 412 |
{ struct net *net; |
72ad937ab net: Add support ... |
413 |
LIST_HEAD(net_exit_list); |
5f256becd [NET]: Basic netw... |
414 415 |
list_del(&ops->list); |
72ad937ab net: Add support ... |
416 417 418 419 |
for_each_net(net) list_add_tail(&net->exit_list, &net_exit_list); ops_exit_list(ops, &net_exit_list); ops_free_list(ops, &net_exit_list); |
5f256becd [NET]: Basic netw... |
420 |
} |
ed160e839 [NET]: Cleanup pe... |
421 |
#else |
f875bae06 net: Automaticall... |
422 423 |
static int __register_pernet_operations(struct list_head *list, struct pernet_operations *ops) |
ed160e839 [NET]: Cleanup pe... |
424 |
{ |
f875bae06 net: Automaticall... |
425 426 427 428 429 430 |
int err = 0; err = ops_init(ops, &init_net); if (err) ops_free(ops, &init_net); return err; |
ed160e839 [NET]: Cleanup pe... |
431 |
} |
f875bae06 net: Automaticall... |
432 |
static void __unregister_pernet_operations(struct pernet_operations *ops) |
ed160e839 [NET]: Cleanup pe... |
433 |
{ |
72ad937ab net: Add support ... |
434 435 436 437 |
LIST_HEAD(net_exit_list); list_add(&init_net.exit_list, &net_exit_list); ops_exit_list(ops, &net_exit_list); ops_free_list(ops, &net_exit_list); |
ed160e839 [NET]: Cleanup pe... |
438 |
} |
f875bae06 net: Automaticall... |
439 440 |
#endif /* CONFIG_NET_NS */ |
ed160e839 [NET]: Cleanup pe... |
441 |
|
c93cf61fd [NETNS]: The net-... |
442 |
static DEFINE_IDA(net_generic_ids); |
f875bae06 net: Automaticall... |
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 |
static int register_pernet_operations(struct list_head *list, struct pernet_operations *ops) { int error; if (ops->id) { again: error = ida_get_new_above(&net_generic_ids, 1, ops->id); if (error < 0) { if (error == -EAGAIN) { ida_pre_get(&net_generic_ids, GFP_KERNEL); goto again; } return error; } } error = __register_pernet_operations(list, ops); |
3a765edad netns: Add an exp... |
460 461 462 463 464 |
if (error) { rcu_barrier(); if (ops->id) ida_remove(&net_generic_ids, *ops->id); } |
f875bae06 net: Automaticall... |
465 466 467 468 469 470 471 472 |
return error; } static void unregister_pernet_operations(struct pernet_operations *ops) { __unregister_pernet_operations(ops); |
3a765edad netns: Add an exp... |
473 |
rcu_barrier(); |
f875bae06 net: Automaticall... |
474 475 476 |
if (ops->id) ida_remove(&net_generic_ids, *ops->id); } |
5f256becd [NET]: Basic netw... |
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 |
/** * register_pernet_subsys - register a network namespace subsystem * @ops: pernet operations structure for the subsystem * * Register a subsystem which has init and exit functions * that are called when network namespaces are created and * destroyed respectively. * * When registered all network namespace init functions are * called for every existing network namespace. Allowing kernel * modules to have a race free view of the set of network namespaces. * * When a new network namespace is created all of the init * methods are called in the order in which they were registered. * * When a network namespace is destroyed all of the exit methods * are called in the reverse of the order with which they were * registered. */ int register_pernet_subsys(struct pernet_operations *ops) { int error; mutex_lock(&net_mutex); error = register_pernet_operations(first_device, ops); mutex_unlock(&net_mutex); return error; } EXPORT_SYMBOL_GPL(register_pernet_subsys); /** * unregister_pernet_subsys - unregister a network namespace subsystem * @ops: pernet operations structure to manipulate * * Remove the pernet operations structure from the list to be |
53379e57a typo fixes in net... |
511 |
* used when network namespaces are created or destroyed. In |
5f256becd [NET]: Basic netw... |
512 513 514 |
* addition run the exit method for all existing network * namespaces. */ |
b3c981d2b netns: rename unr... |
515 |
void unregister_pernet_subsys(struct pernet_operations *ops) |
5f256becd [NET]: Basic netw... |
516 517 |
{ mutex_lock(&net_mutex); |
b3c981d2b netns: rename unr... |
518 |
unregister_pernet_operations(ops); |
5f256becd [NET]: Basic netw... |
519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 |
mutex_unlock(&net_mutex); } EXPORT_SYMBOL_GPL(unregister_pernet_subsys); /** * register_pernet_device - register a network namespace device * @ops: pernet operations structure for the subsystem * * Register a device which has init and exit functions * that are called when network namespaces are created and * destroyed respectively. * * When registered all network namespace init functions are * called for every existing network namespace. Allowing kernel * modules to have a race free view of the set of network namespaces. * * When a new network namespace is created all of the init * methods are called in the order in which they were registered. * * When a network namespace is destroyed all of the exit methods * are called in the reverse of the order with which they were * registered. */ int register_pernet_device(struct pernet_operations *ops) { int error; mutex_lock(&net_mutex); error = register_pernet_operations(&pernet_list, ops); if (!error && (first_device == &pernet_list)) first_device = &ops->list; mutex_unlock(&net_mutex); return error; } EXPORT_SYMBOL_GPL(register_pernet_device); /** * unregister_pernet_device - unregister a network namespace netdevice * @ops: pernet operations structure to manipulate * * Remove the pernet operations structure from the list to be |
53379e57a typo fixes in net... |
559 |
* used when network namespaces are created or destroyed. In |
5f256becd [NET]: Basic netw... |
560 561 562 563 564 565 566 567 568 569 570 571 |
* addition run the exit method for all existing network * namespaces. */ void unregister_pernet_device(struct pernet_operations *ops) { mutex_lock(&net_mutex); if (&ops->list == first_device) first_device = first_device->next; unregister_pernet_operations(ops); mutex_unlock(&net_mutex); } EXPORT_SYMBOL_GPL(unregister_pernet_device); |
13b6f5762 ns proc: Add supp... |
572 573 574 575 |
#ifdef CONFIG_NET_NS static void *netns_get(struct task_struct *task) { |
f06305294 net: Allow settin... |
576 577 |
struct net *net = NULL; struct nsproxy *nsproxy; |
13b6f5762 ns proc: Add supp... |
578 |
rcu_read_lock(); |
f06305294 net: Allow settin... |
579 580 581 |
nsproxy = task_nsproxy(task); if (nsproxy) net = get_net(nsproxy->net_ns); |
13b6f5762 ns proc: Add supp... |
582 |
rcu_read_unlock(); |
f06305294 net: Allow settin... |
583 |
|
13b6f5762 ns proc: Add supp... |
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 |
return net; } static void netns_put(void *ns) { put_net(ns); } static int netns_install(struct nsproxy *nsproxy, void *ns) { put_net(nsproxy->net_ns); nsproxy->net_ns = get_net(ns); return 0; } const struct proc_ns_operations netns_operations = { .name = "net", .type = CLONE_NEWNET, .get = netns_get, .put = netns_put, .install = netns_install, }; #endif |