aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/fork.c
diff options
context:
space:
mode:
authorLachlan McIlroy <lachlan@redback.melbourne.sgi.com>2008-02-17 21:51:42 -0500
committerLachlan McIlroy <lachlan@redback.melbourne.sgi.com>2008-02-17 21:51:42 -0500
commitc58310bf4933986513020fa90b4190c7492995ae (patch)
tree143f2c7578d02ebef5db8fc57ae69e951ae0e2ee /kernel/fork.c
parent269cdfaf769f5cd831284cc831790c7c5038040f (diff)
parent1309d4e68497184d2fd87e892ddf14076c2bda98 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into for-linus
Diffstat (limited to 'kernel/fork.c')
-rw-r--r--kernel/fork.c65
1 files changed, 41 insertions, 24 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index 05e0b6f4365b..dd249c37b3a3 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -40,6 +40,7 @@
40#include <linux/ptrace.h> 40#include <linux/ptrace.h>
41#include <linux/mount.h> 41#include <linux/mount.h>
42#include <linux/audit.h> 42#include <linux/audit.h>
43#include <linux/memcontrol.h>
43#include <linux/profile.h> 44#include <linux/profile.h>
44#include <linux/rmap.h> 45#include <linux/rmap.h>
45#include <linux/acct.h> 46#include <linux/acct.h>
@@ -325,7 +326,7 @@ static inline int mm_alloc_pgd(struct mm_struct * mm)
325 326
326static inline void mm_free_pgd(struct mm_struct * mm) 327static inline void mm_free_pgd(struct mm_struct * mm)
327{ 328{
328 pgd_free(mm->pgd); 329 pgd_free(mm, mm->pgd);
329} 330}
330#else 331#else
331#define dup_mmap(mm, oldmm) (0) 332#define dup_mmap(mm, oldmm) (0)
@@ -340,7 +341,7 @@ __cacheline_aligned_in_smp DEFINE_SPINLOCK(mmlist_lock);
340 341
341#include <linux/init_task.h> 342#include <linux/init_task.h>
342 343
343static struct mm_struct * mm_init(struct mm_struct * mm) 344static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p)
344{ 345{
345 atomic_set(&mm->mm_users, 1); 346 atomic_set(&mm->mm_users, 1);
346 atomic_set(&mm->mm_count, 1); 347 atomic_set(&mm->mm_count, 1);
@@ -357,11 +358,14 @@ static struct mm_struct * mm_init(struct mm_struct * mm)
357 mm->ioctx_list = NULL; 358 mm->ioctx_list = NULL;
358 mm->free_area_cache = TASK_UNMAPPED_BASE; 359 mm->free_area_cache = TASK_UNMAPPED_BASE;
359 mm->cached_hole_size = ~0UL; 360 mm->cached_hole_size = ~0UL;
361 mm_init_cgroup(mm, p);
360 362
361 if (likely(!mm_alloc_pgd(mm))) { 363 if (likely(!mm_alloc_pgd(mm))) {
362 mm->def_flags = 0; 364 mm->def_flags = 0;
363 return mm; 365 return mm;
364 } 366 }
367
368 mm_free_cgroup(mm);
365 free_mm(mm); 369 free_mm(mm);
366 return NULL; 370 return NULL;
367} 371}
@@ -376,7 +380,7 @@ struct mm_struct * mm_alloc(void)
376 mm = allocate_mm(); 380 mm = allocate_mm();
377 if (mm) { 381 if (mm) {
378 memset(mm, 0, sizeof(*mm)); 382 memset(mm, 0, sizeof(*mm));
379 mm = mm_init(mm); 383 mm = mm_init(mm, current);
380 } 384 }
381 return mm; 385 return mm;
382} 386}
@@ -386,10 +390,11 @@ struct mm_struct * mm_alloc(void)
386 * is dropped: either by a lazy thread or by 390 * is dropped: either by a lazy thread or by
387 * mmput. Free the page directory and the mm. 391 * mmput. Free the page directory and the mm.
388 */ 392 */
389void fastcall __mmdrop(struct mm_struct *mm) 393void __mmdrop(struct mm_struct *mm)
390{ 394{
391 BUG_ON(mm == &init_mm); 395 BUG_ON(mm == &init_mm);
392 mm_free_pgd(mm); 396 mm_free_pgd(mm);
397 mm_free_cgroup(mm);
393 destroy_context(mm); 398 destroy_context(mm);
394 free_mm(mm); 399 free_mm(mm);
395} 400}
@@ -511,7 +516,7 @@ static struct mm_struct *dup_mm(struct task_struct *tsk)
511 mm->token_priority = 0; 516 mm->token_priority = 0;
512 mm->last_interval = 0; 517 mm->last_interval = 0;
513 518
514 if (!mm_init(mm)) 519 if (!mm_init(mm, tsk))
515 goto fail_nomem; 520 goto fail_nomem;
516 521
517 if (init_new_context(tsk, mm)) 522 if (init_new_context(tsk, mm))
@@ -595,16 +600,16 @@ static struct fs_struct *__copy_fs_struct(struct fs_struct *old)
595 rwlock_init(&fs->lock); 600 rwlock_init(&fs->lock);
596 fs->umask = old->umask; 601 fs->umask = old->umask;
597 read_lock(&old->lock); 602 read_lock(&old->lock);
598 fs->rootmnt = mntget(old->rootmnt); 603 fs->root = old->root;
599 fs->root = dget(old->root); 604 path_get(&old->root);
600 fs->pwdmnt = mntget(old->pwdmnt); 605 fs->pwd = old->pwd;
601 fs->pwd = dget(old->pwd); 606 path_get(&old->pwd);
602 if (old->altroot) { 607 if (old->altroot.dentry) {
603 fs->altrootmnt = mntget(old->altrootmnt); 608 fs->altroot = old->altroot;
604 fs->altroot = dget(old->altroot); 609 path_get(&old->altroot);
605 } else { 610 } else {
606 fs->altrootmnt = NULL; 611 fs->altroot.mnt = NULL;
607 fs->altroot = NULL; 612 fs->altroot.dentry = NULL;
608 } 613 }
609 read_unlock(&old->lock); 614 read_unlock(&old->lock);
610 } 615 }
@@ -904,7 +909,6 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
904 hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 909 hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
905 sig->it_real_incr.tv64 = 0; 910 sig->it_real_incr.tv64 = 0;
906 sig->real_timer.function = it_real_fn; 911 sig->real_timer.function = it_real_fn;
907 sig->tsk = tsk;
908 912
909 sig->it_virt_expires = cputime_zero; 913 sig->it_virt_expires = cputime_zero;
910 sig->it_virt_incr = cputime_zero; 914 sig->it_virt_incr = cputime_zero;
@@ -1118,6 +1122,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1118#ifdef CONFIG_SECURITY 1122#ifdef CONFIG_SECURITY
1119 p->security = NULL; 1123 p->security = NULL;
1120#endif 1124#endif
1125 p->cap_bset = current->cap_bset;
1121 p->io_context = NULL; 1126 p->io_context = NULL;
1122 p->audit_context = NULL; 1127 p->audit_context = NULL;
1123 cgroup_fork(p); 1128 cgroup_fork(p);
@@ -1332,6 +1337,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1332 if (clone_flags & CLONE_NEWPID) 1337 if (clone_flags & CLONE_NEWPID)
1333 p->nsproxy->pid_ns->child_reaper = p; 1338 p->nsproxy->pid_ns->child_reaper = p;
1334 1339
1340 p->signal->leader_pid = pid;
1335 p->signal->tty = current->signal->tty; 1341 p->signal->tty = current->signal->tty;
1336 set_task_pgrp(p, task_pgrp_nr(current)); 1342 set_task_pgrp(p, task_pgrp_nr(current));
1337 set_task_session(p, task_session_nr(current)); 1343 set_task_session(p, task_session_nr(current));
@@ -1398,7 +1404,7 @@ fork_out:
1398 return ERR_PTR(retval); 1404 return ERR_PTR(retval);
1399} 1405}
1400 1406
1401noinline struct pt_regs * __devinit __attribute__((weak)) idle_regs(struct pt_regs *regs) 1407noinline struct pt_regs * __cpuinit __attribute__((weak)) idle_regs(struct pt_regs *regs)
1402{ 1408{
1403 memset(regs, 0, sizeof(struct pt_regs)); 1409 memset(regs, 0, sizeof(struct pt_regs));
1404 return regs; 1410 return regs;
@@ -1450,6 +1456,23 @@ long do_fork(unsigned long clone_flags,
1450 int trace = 0; 1456 int trace = 0;
1451 long nr; 1457 long nr;
1452 1458
1459 /*
1460 * We hope to recycle these flags after 2.6.26
1461 */
1462 if (unlikely(clone_flags & CLONE_STOPPED)) {
1463 static int __read_mostly count = 100;
1464
1465 if (count > 0 && printk_ratelimit()) {
1466 char comm[TASK_COMM_LEN];
1467
1468 count--;
1469 printk(KERN_INFO "fork(): process `%s' used deprecated "
1470 "clone flags 0x%lx\n",
1471 get_task_comm(comm, current),
1472 clone_flags & CLONE_STOPPED);
1473 }
1474 }
1475
1453 if (unlikely(current->ptrace)) { 1476 if (unlikely(current->ptrace)) {
1454 trace = fork_traceflag (clone_flags); 1477 trace = fork_traceflag (clone_flags);
1455 if (trace) 1478 if (trace)
@@ -1465,13 +1488,7 @@ long do_fork(unsigned long clone_flags,
1465 if (!IS_ERR(p)) { 1488 if (!IS_ERR(p)) {
1466 struct completion vfork; 1489 struct completion vfork;
1467 1490
1468 /* 1491 nr = task_pid_vnr(p);
1469 * this is enough to call pid_nr_ns here, but this if
1470 * improves optimisation of regular fork()
1471 */
1472 nr = (clone_flags & CLONE_NEWPID) ?
1473 task_pid_nr_ns(p, current->nsproxy->pid_ns) :
1474 task_pid_vnr(p);
1475 1492
1476 if (clone_flags & CLONE_PARENT_SETTID) 1493 if (clone_flags & CLONE_PARENT_SETTID)
1477 put_user(nr, parent_tidptr); 1494 put_user(nr, parent_tidptr);
@@ -1492,7 +1509,7 @@ long do_fork(unsigned long clone_flags,
1492 if (!(clone_flags & CLONE_STOPPED)) 1509 if (!(clone_flags & CLONE_STOPPED))
1493 wake_up_new_task(p, clone_flags); 1510 wake_up_new_task(p, clone_flags);
1494 else 1511 else
1495 p->state = TASK_STOPPED; 1512 __set_task_state(p, TASK_STOPPED);
1496 1513
1497 if (unlikely (trace)) { 1514 if (unlikely (trace)) {
1498 current->ptrace_message = nr; 1515 current->ptrace_message = nr;