diff options
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 37 |
1 files changed, 28 insertions, 9 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 98b450876f93..5447dc7defa9 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -65,6 +65,7 @@ | |||
65 | #include <linux/perf_event.h> | 65 | #include <linux/perf_event.h> |
66 | #include <linux/posix-timers.h> | 66 | #include <linux/posix-timers.h> |
67 | #include <linux/user-return-notifier.h> | 67 | #include <linux/user-return-notifier.h> |
68 | #include <linux/oom.h> | ||
68 | 69 | ||
69 | #include <asm/pgtable.h> | 70 | #include <asm/pgtable.h> |
70 | #include <asm/pgalloc.h> | 71 | #include <asm/pgalloc.h> |
@@ -272,6 +273,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) | |||
272 | 273 | ||
273 | setup_thread_stack(tsk, orig); | 274 | setup_thread_stack(tsk, orig); |
274 | clear_user_return_notifier(tsk); | 275 | clear_user_return_notifier(tsk); |
276 | clear_tsk_need_resched(tsk); | ||
275 | stackend = end_of_stack(tsk); | 277 | stackend = end_of_stack(tsk); |
276 | *stackend = STACK_END_MAGIC; /* for overflow detection */ | 278 | *stackend = STACK_END_MAGIC; /* for overflow detection */ |
277 | 279 | ||
@@ -300,7 +302,7 @@ out: | |||
300 | #ifdef CONFIG_MMU | 302 | #ifdef CONFIG_MMU |
301 | static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) | 303 | static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) |
302 | { | 304 | { |
303 | struct vm_area_struct *mpnt, *tmp, **pprev; | 305 | struct vm_area_struct *mpnt, *tmp, *prev, **pprev; |
304 | struct rb_node **rb_link, *rb_parent; | 306 | struct rb_node **rb_link, *rb_parent; |
305 | int retval; | 307 | int retval; |
306 | unsigned long charge; | 308 | unsigned long charge; |
@@ -328,6 +330,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) | |||
328 | if (retval) | 330 | if (retval) |
329 | goto out; | 331 | goto out; |
330 | 332 | ||
333 | prev = NULL; | ||
331 | for (mpnt = oldmm->mmap; mpnt; mpnt = mpnt->vm_next) { | 334 | for (mpnt = oldmm->mmap; mpnt; mpnt = mpnt->vm_next) { |
332 | struct file *file; | 335 | struct file *file; |
333 | 336 | ||
@@ -355,11 +358,11 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) | |||
355 | if (IS_ERR(pol)) | 358 | if (IS_ERR(pol)) |
356 | goto fail_nomem_policy; | 359 | goto fail_nomem_policy; |
357 | vma_set_policy(tmp, pol); | 360 | vma_set_policy(tmp, pol); |
361 | tmp->vm_mm = mm; | ||
358 | if (anon_vma_fork(tmp, mpnt)) | 362 | if (anon_vma_fork(tmp, mpnt)) |
359 | goto fail_nomem_anon_vma_fork; | 363 | goto fail_nomem_anon_vma_fork; |
360 | tmp->vm_flags &= ~VM_LOCKED; | 364 | tmp->vm_flags &= ~VM_LOCKED; |
361 | tmp->vm_mm = mm; | 365 | tmp->vm_next = tmp->vm_prev = NULL; |
362 | tmp->vm_next = NULL; | ||
363 | file = tmp->vm_file; | 366 | file = tmp->vm_file; |
364 | if (file) { | 367 | if (file) { |
365 | struct inode *inode = file->f_path.dentry->d_inode; | 368 | struct inode *inode = file->f_path.dentry->d_inode; |
@@ -392,6 +395,8 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) | |||
392 | */ | 395 | */ |
393 | *pprev = tmp; | 396 | *pprev = tmp; |
394 | pprev = &tmp->vm_next; | 397 | pprev = &tmp->vm_next; |
398 | tmp->vm_prev = prev; | ||
399 | prev = tmp; | ||
395 | 400 | ||
396 | __vma_link_rb(mm, tmp, rb_link, rb_parent); | 401 | __vma_link_rb(mm, tmp, rb_link, rb_parent); |
397 | rb_link = &tmp->vm_rb.rb_right; | 402 | rb_link = &tmp->vm_rb.rb_right; |
@@ -485,6 +490,7 @@ static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p) | |||
485 | mm->cached_hole_size = ~0UL; | 490 | mm->cached_hole_size = ~0UL; |
486 | mm_init_aio(mm); | 491 | mm_init_aio(mm); |
487 | mm_init_owner(mm, p); | 492 | mm_init_owner(mm, p); |
493 | atomic_set(&mm->oom_disable_count, 0); | ||
488 | 494 | ||
489 | if (likely(!mm_alloc_pgd(mm))) { | 495 | if (likely(!mm_alloc_pgd(mm))) { |
490 | mm->def_flags = 0; | 496 | mm->def_flags = 0; |
@@ -738,6 +744,8 @@ good_mm: | |||
738 | /* Initializing for Swap token stuff */ | 744 | /* Initializing for Swap token stuff */ |
739 | mm->token_priority = 0; | 745 | mm->token_priority = 0; |
740 | mm->last_interval = 0; | 746 | mm->last_interval = 0; |
747 | if (tsk->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) | ||
748 | atomic_inc(&mm->oom_disable_count); | ||
741 | 749 | ||
742 | tsk->mm = mm; | 750 | tsk->mm = mm; |
743 | tsk->active_mm = mm; | 751 | tsk->active_mm = mm; |
@@ -752,13 +760,13 @@ static int copy_fs(unsigned long clone_flags, struct task_struct *tsk) | |||
752 | struct fs_struct *fs = current->fs; | 760 | struct fs_struct *fs = current->fs; |
753 | if (clone_flags & CLONE_FS) { | 761 | if (clone_flags & CLONE_FS) { |
754 | /* tsk->fs is already what we want */ | 762 | /* tsk->fs is already what we want */ |
755 | write_lock(&fs->lock); | 763 | spin_lock(&fs->lock); |
756 | if (fs->in_exec) { | 764 | if (fs->in_exec) { |
757 | write_unlock(&fs->lock); | 765 | spin_unlock(&fs->lock); |
758 | return -EAGAIN; | 766 | return -EAGAIN; |
759 | } | 767 | } |
760 | fs->users++; | 768 | fs->users++; |
761 | write_unlock(&fs->lock); | 769 | spin_unlock(&fs->lock); |
762 | return 0; | 770 | return 0; |
763 | } | 771 | } |
764 | tsk->fs = copy_fs_struct(fs); | 772 | tsk->fs = copy_fs_struct(fs); |
@@ -901,6 +909,8 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) | |||
901 | sig->oom_adj = current->signal->oom_adj; | 909 | sig->oom_adj = current->signal->oom_adj; |
902 | sig->oom_score_adj = current->signal->oom_score_adj; | 910 | sig->oom_score_adj = current->signal->oom_score_adj; |
903 | 911 | ||
912 | mutex_init(&sig->cred_guard_mutex); | ||
913 | |||
904 | return 0; | 914 | return 0; |
905 | } | 915 | } |
906 | 916 | ||
@@ -1296,8 +1306,13 @@ bad_fork_cleanup_io: | |||
1296 | bad_fork_cleanup_namespaces: | 1306 | bad_fork_cleanup_namespaces: |
1297 | exit_task_namespaces(p); | 1307 | exit_task_namespaces(p); |
1298 | bad_fork_cleanup_mm: | 1308 | bad_fork_cleanup_mm: |
1299 | if (p->mm) | 1309 | if (p->mm) { |
1310 | task_lock(p); | ||
1311 | if (p->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) | ||
1312 | atomic_dec(&p->mm->oom_disable_count); | ||
1313 | task_unlock(p); | ||
1300 | mmput(p->mm); | 1314 | mmput(p->mm); |
1315 | } | ||
1301 | bad_fork_cleanup_signal: | 1316 | bad_fork_cleanup_signal: |
1302 | if (!(clone_flags & CLONE_THREAD)) | 1317 | if (!(clone_flags & CLONE_THREAD)) |
1303 | free_signal_struct(p->signal); | 1318 | free_signal_struct(p->signal); |
@@ -1676,13 +1691,13 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) | |||
1676 | 1691 | ||
1677 | if (new_fs) { | 1692 | if (new_fs) { |
1678 | fs = current->fs; | 1693 | fs = current->fs; |
1679 | write_lock(&fs->lock); | 1694 | spin_lock(&fs->lock); |
1680 | current->fs = new_fs; | 1695 | current->fs = new_fs; |
1681 | if (--fs->users) | 1696 | if (--fs->users) |
1682 | new_fs = NULL; | 1697 | new_fs = NULL; |
1683 | else | 1698 | else |
1684 | new_fs = fs; | 1699 | new_fs = fs; |
1685 | write_unlock(&fs->lock); | 1700 | spin_unlock(&fs->lock); |
1686 | } | 1701 | } |
1687 | 1702 | ||
1688 | if (new_mm) { | 1703 | if (new_mm) { |
@@ -1690,6 +1705,10 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) | |||
1690 | active_mm = current->active_mm; | 1705 | active_mm = current->active_mm; |
1691 | current->mm = new_mm; | 1706 | current->mm = new_mm; |
1692 | current->active_mm = new_mm; | 1707 | current->active_mm = new_mm; |
1708 | if (current->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) { | ||
1709 | atomic_dec(&mm->oom_disable_count); | ||
1710 | atomic_inc(&new_mm->oom_disable_count); | ||
1711 | } | ||
1693 | activate_mm(active_mm, new_mm); | 1712 | activate_mm(active_mm, new_mm); |
1694 | new_mm = mm; | 1713 | new_mm = mm; |
1695 | } | 1714 | } |