diff options
author | Lachlan McIlroy <lachlan@redback.melbourne.sgi.com> | 2008-02-17 21:51:42 -0500 |
---|---|---|
committer | Lachlan McIlroy <lachlan@redback.melbourne.sgi.com> | 2008-02-17 21:51:42 -0500 |
commit | c58310bf4933986513020fa90b4190c7492995ae (patch) | |
tree | 143f2c7578d02ebef5db8fc57ae69e951ae0e2ee /kernel/fork.c | |
parent | 269cdfaf769f5cd831284cc831790c7c5038040f (diff) | |
parent | 1309d4e68497184d2fd87e892ddf14076c2bda98 (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.c | 65 |
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 | ||
326 | static inline void mm_free_pgd(struct mm_struct * mm) | 327 | static 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 | ||
343 | static struct mm_struct * mm_init(struct mm_struct * mm) | 344 | static 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 | */ |
389 | void fastcall __mmdrop(struct mm_struct *mm) | 393 | void __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 | ||
1401 | noinline struct pt_regs * __devinit __attribute__((weak)) idle_regs(struct pt_regs *regs) | 1407 | noinline 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; |