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