diff options
Diffstat (limited to 'kernel/pid.c')
-rw-r--r-- | kernel/pid.c | 75 |
1 files changed, 50 insertions, 25 deletions
diff --git a/kernel/pid.c b/kernel/pid.c index aebd4f5aaf41..de9af600006f 100644 --- a/kernel/pid.c +++ b/kernel/pid.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Generic pidhash and scalable, time-bounded PID allocator | 2 | * Generic pidhash and scalable, time-bounded PID allocator |
3 | * | 3 | * |
4 | * (C) 2002-2003 William Irwin, IBM | 4 | * (C) 2002-2003 Nadia Yvette Chambers, IBM |
5 | * (C) 2004 William Irwin, Oracle | 5 | * (C) 2004 Nadia Yvette Chambers, Oracle |
6 | * (C) 2002-2004 Ingo Molnar, Red Hat | 6 | * (C) 2002-2004 Ingo Molnar, Red Hat |
7 | * | 7 | * |
8 | * pid-structures are backing objects for tasks sharing a given ID to chain | 8 | * pid-structures are backing objects for tasks sharing a given ID to chain |
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/pid_namespace.h> | 36 | #include <linux/pid_namespace.h> |
37 | #include <linux/init_task.h> | 37 | #include <linux/init_task.h> |
38 | #include <linux/syscalls.h> | 38 | #include <linux/syscalls.h> |
39 | #include <linux/proc_fs.h> | ||
39 | 40 | ||
40 | #define pid_hashfn(nr, ns) \ | 41 | #define pid_hashfn(nr, ns) \ |
41 | hash_long((unsigned long)nr + (unsigned long)ns, pidhash_shift) | 42 | hash_long((unsigned long)nr + (unsigned long)ns, pidhash_shift) |
@@ -78,24 +79,11 @@ struct pid_namespace init_pid_ns = { | |||
78 | .last_pid = 0, | 79 | .last_pid = 0, |
79 | .level = 0, | 80 | .level = 0, |
80 | .child_reaper = &init_task, | 81 | .child_reaper = &init_task, |
82 | .user_ns = &init_user_ns, | ||
83 | .proc_inum = PROC_PID_INIT_INO, | ||
81 | }; | 84 | }; |
82 | EXPORT_SYMBOL_GPL(init_pid_ns); | 85 | EXPORT_SYMBOL_GPL(init_pid_ns); |
83 | 86 | ||
84 | int is_container_init(struct task_struct *tsk) | ||
85 | { | ||
86 | int ret = 0; | ||
87 | struct pid *pid; | ||
88 | |||
89 | rcu_read_lock(); | ||
90 | pid = task_pid(tsk); | ||
91 | if (pid != NULL && pid->numbers[pid->level].nr == 1) | ||
92 | ret = 1; | ||
93 | rcu_read_unlock(); | ||
94 | |||
95 | return ret; | ||
96 | } | ||
97 | EXPORT_SYMBOL(is_container_init); | ||
98 | |||
99 | /* | 87 | /* |
100 | * Note: disable interrupts while the pidmap_lock is held as an | 88 | * Note: disable interrupts while the pidmap_lock is held as an |
101 | * interrupt might come in and do read_lock(&tasklist_lock). | 89 | * interrupt might come in and do read_lock(&tasklist_lock). |
@@ -269,8 +257,23 @@ void free_pid(struct pid *pid) | |||
269 | unsigned long flags; | 257 | unsigned long flags; |
270 | 258 | ||
271 | spin_lock_irqsave(&pidmap_lock, flags); | 259 | spin_lock_irqsave(&pidmap_lock, flags); |
272 | for (i = 0; i <= pid->level; i++) | 260 | for (i = 0; i <= pid->level; i++) { |
273 | hlist_del_rcu(&pid->numbers[i].pid_chain); | 261 | struct upid *upid = pid->numbers + i; |
262 | struct pid_namespace *ns = upid->ns; | ||
263 | hlist_del_rcu(&upid->pid_chain); | ||
264 | switch(--ns->nr_hashed) { | ||
265 | case 1: | ||
266 | /* When all that is left in the pid namespace | ||
267 | * is the reaper wake up the reaper. The reaper | ||
268 | * may be sleeping in zap_pid_ns_processes(). | ||
269 | */ | ||
270 | wake_up_process(ns->child_reaper); | ||
271 | break; | ||
272 | case 0: | ||
273 | schedule_work(&ns->proc_work); | ||
274 | break; | ||
275 | } | ||
276 | } | ||
274 | spin_unlock_irqrestore(&pidmap_lock, flags); | 277 | spin_unlock_irqrestore(&pidmap_lock, flags); |
275 | 278 | ||
276 | for (i = 0; i <= pid->level; i++) | 279 | for (i = 0; i <= pid->level; i++) |
@@ -292,6 +295,7 @@ struct pid *alloc_pid(struct pid_namespace *ns) | |||
292 | goto out; | 295 | goto out; |
293 | 296 | ||
294 | tmp = ns; | 297 | tmp = ns; |
298 | pid->level = ns->level; | ||
295 | for (i = ns->level; i >= 0; i--) { | 299 | for (i = ns->level; i >= 0; i--) { |
296 | nr = alloc_pidmap(tmp); | 300 | nr = alloc_pidmap(tmp); |
297 | if (nr < 0) | 301 | if (nr < 0) |
@@ -302,22 +306,32 @@ struct pid *alloc_pid(struct pid_namespace *ns) | |||
302 | tmp = tmp->parent; | 306 | tmp = tmp->parent; |
303 | } | 307 | } |
304 | 308 | ||
309 | if (unlikely(is_child_reaper(pid))) { | ||
310 | if (pid_ns_prepare_proc(ns)) | ||
311 | goto out_free; | ||
312 | } | ||
313 | |||
305 | get_pid_ns(ns); | 314 | get_pid_ns(ns); |
306 | pid->level = ns->level; | ||
307 | atomic_set(&pid->count, 1); | 315 | atomic_set(&pid->count, 1); |
308 | for (type = 0; type < PIDTYPE_MAX; ++type) | 316 | for (type = 0; type < PIDTYPE_MAX; ++type) |
309 | INIT_HLIST_HEAD(&pid->tasks[type]); | 317 | INIT_HLIST_HEAD(&pid->tasks[type]); |
310 | 318 | ||
311 | upid = pid->numbers + ns->level; | 319 | upid = pid->numbers + ns->level; |
312 | spin_lock_irq(&pidmap_lock); | 320 | spin_lock_irq(&pidmap_lock); |
313 | for ( ; upid >= pid->numbers; --upid) | 321 | if (!(ns->nr_hashed & PIDNS_HASH_ADDING)) |
322 | goto out_unlock; | ||
323 | for ( ; upid >= pid->numbers; --upid) { | ||
314 | hlist_add_head_rcu(&upid->pid_chain, | 324 | hlist_add_head_rcu(&upid->pid_chain, |
315 | &pid_hash[pid_hashfn(upid->nr, upid->ns)]); | 325 | &pid_hash[pid_hashfn(upid->nr, upid->ns)]); |
326 | upid->ns->nr_hashed++; | ||
327 | } | ||
316 | spin_unlock_irq(&pidmap_lock); | 328 | spin_unlock_irq(&pidmap_lock); |
317 | 329 | ||
318 | out: | 330 | out: |
319 | return pid; | 331 | return pid; |
320 | 332 | ||
333 | out_unlock: | ||
334 | spin_unlock(&pidmap_lock); | ||
321 | out_free: | 335 | out_free: |
322 | while (++i <= ns->level) | 336 | while (++i <= ns->level) |
323 | free_pidmap(pid->numbers + i); | 337 | free_pidmap(pid->numbers + i); |
@@ -327,6 +341,13 @@ out_free: | |||
327 | goto out; | 341 | goto out; |
328 | } | 342 | } |
329 | 343 | ||
344 | void disable_pid_allocation(struct pid_namespace *ns) | ||
345 | { | ||
346 | spin_lock_irq(&pidmap_lock); | ||
347 | ns->nr_hashed &= ~PIDNS_HASH_ADDING; | ||
348 | spin_unlock_irq(&pidmap_lock); | ||
349 | } | ||
350 | |||
330 | struct pid *find_pid_ns(int nr, struct pid_namespace *ns) | 351 | struct pid *find_pid_ns(int nr, struct pid_namespace *ns) |
331 | { | 352 | { |
332 | struct hlist_node *elem; | 353 | struct hlist_node *elem; |
@@ -344,7 +365,7 @@ EXPORT_SYMBOL_GPL(find_pid_ns); | |||
344 | 365 | ||
345 | struct pid *find_vpid(int nr) | 366 | struct pid *find_vpid(int nr) |
346 | { | 367 | { |
347 | return find_pid_ns(nr, current->nsproxy->pid_ns); | 368 | return find_pid_ns(nr, task_active_pid_ns(current)); |
348 | } | 369 | } |
349 | EXPORT_SYMBOL_GPL(find_vpid); | 370 | EXPORT_SYMBOL_GPL(find_vpid); |
350 | 371 | ||
@@ -428,7 +449,7 @@ struct task_struct *find_task_by_pid_ns(pid_t nr, struct pid_namespace *ns) | |||
428 | 449 | ||
429 | struct task_struct *find_task_by_vpid(pid_t vnr) | 450 | struct task_struct *find_task_by_vpid(pid_t vnr) |
430 | { | 451 | { |
431 | return find_task_by_pid_ns(vnr, current->nsproxy->pid_ns); | 452 | return find_task_by_pid_ns(vnr, task_active_pid_ns(current)); |
432 | } | 453 | } |
433 | 454 | ||
434 | struct pid *get_task_pid(struct task_struct *task, enum pid_type type) | 455 | struct pid *get_task_pid(struct task_struct *task, enum pid_type type) |
@@ -483,7 +504,7 @@ EXPORT_SYMBOL_GPL(pid_nr_ns); | |||
483 | 504 | ||
484 | pid_t pid_vnr(struct pid *pid) | 505 | pid_t pid_vnr(struct pid *pid) |
485 | { | 506 | { |
486 | return pid_nr_ns(pid, current->nsproxy->pid_ns); | 507 | return pid_nr_ns(pid, task_active_pid_ns(current)); |
487 | } | 508 | } |
488 | EXPORT_SYMBOL_GPL(pid_vnr); | 509 | EXPORT_SYMBOL_GPL(pid_vnr); |
489 | 510 | ||
@@ -494,7 +515,7 @@ pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type, | |||
494 | 515 | ||
495 | rcu_read_lock(); | 516 | rcu_read_lock(); |
496 | if (!ns) | 517 | if (!ns) |
497 | ns = current->nsproxy->pid_ns; | 518 | ns = task_active_pid_ns(current); |
498 | if (likely(pid_alive(task))) { | 519 | if (likely(pid_alive(task))) { |
499 | if (type != PIDTYPE_PID) | 520 | if (type != PIDTYPE_PID) |
500 | task = task->group_leader; | 521 | task = task->group_leader; |
@@ -558,6 +579,9 @@ void __init pidhash_init(void) | |||
558 | 579 | ||
559 | void __init pidmap_init(void) | 580 | void __init pidmap_init(void) |
560 | { | 581 | { |
582 | /* Veryify no one has done anything silly */ | ||
583 | BUILD_BUG_ON(PID_MAX_LIMIT >= PIDNS_HASH_ADDING); | ||
584 | |||
561 | /* bump default and minimum pid_max based on number of cpus */ | 585 | /* bump default and minimum pid_max based on number of cpus */ |
562 | pid_max = min(pid_max_max, max_t(int, pid_max, | 586 | pid_max = min(pid_max_max, max_t(int, pid_max, |
563 | PIDS_PER_CPU_DEFAULT * num_possible_cpus())); | 587 | PIDS_PER_CPU_DEFAULT * num_possible_cpus())); |
@@ -569,6 +593,7 @@ void __init pidmap_init(void) | |||
569 | /* Reserve PID 0. We never call free_pidmap(0) */ | 593 | /* Reserve PID 0. We never call free_pidmap(0) */ |
570 | set_bit(0, init_pid_ns.pidmap[0].page); | 594 | set_bit(0, init_pid_ns.pidmap[0].page); |
571 | atomic_dec(&init_pid_ns.pidmap[0].nr_free); | 595 | atomic_dec(&init_pid_ns.pidmap[0].nr_free); |
596 | init_pid_ns.nr_hashed = PIDNS_HASH_ADDING; | ||
572 | 597 | ||
573 | init_pid_ns.pid_cachep = KMEM_CACHE(pid, | 598 | init_pid_ns.pid_cachep = KMEM_CACHE(pid, |
574 | SLAB_HWCACHE_ALIGN | SLAB_PANIC); | 599 | SLAB_HWCACHE_ALIGN | SLAB_PANIC); |