diff options
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 30 |
1 files changed, 20 insertions, 10 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index a28d11e10877..b65187f0c74e 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -208,8 +208,10 @@ static inline int dup_mmap(struct mm_struct * mm, struct mm_struct * oldmm) | |||
208 | struct file *file; | 208 | struct file *file; |
209 | 209 | ||
210 | if (mpnt->vm_flags & VM_DONTCOPY) { | 210 | if (mpnt->vm_flags & VM_DONTCOPY) { |
211 | long pages = vma_pages(mpnt); | ||
212 | mm->total_vm -= pages; | ||
211 | __vm_stat_account(mm, mpnt->vm_flags, mpnt->vm_file, | 213 | __vm_stat_account(mm, mpnt->vm_flags, mpnt->vm_file, |
212 | -vma_pages(mpnt)); | 214 | -pages); |
213 | continue; | 215 | continue; |
214 | } | 216 | } |
215 | charge = 0; | 217 | charge = 0; |
@@ -1003,9 +1005,6 @@ static task_t *copy_process(unsigned long clone_flags, | |||
1003 | p->pdeath_signal = 0; | 1005 | p->pdeath_signal = 0; |
1004 | p->exit_state = 0; | 1006 | p->exit_state = 0; |
1005 | 1007 | ||
1006 | /* Perform scheduler related setup */ | ||
1007 | sched_fork(p); | ||
1008 | |||
1009 | /* | 1008 | /* |
1010 | * Ok, make it visible to the rest of the system. | 1009 | * Ok, make it visible to the rest of the system. |
1011 | * We dont wake it up yet. | 1010 | * We dont wake it up yet. |
@@ -1014,18 +1013,24 @@ static task_t *copy_process(unsigned long clone_flags, | |||
1014 | INIT_LIST_HEAD(&p->ptrace_children); | 1013 | INIT_LIST_HEAD(&p->ptrace_children); |
1015 | INIT_LIST_HEAD(&p->ptrace_list); | 1014 | INIT_LIST_HEAD(&p->ptrace_list); |
1016 | 1015 | ||
1016 | /* Perform scheduler related setup. Assign this task to a CPU. */ | ||
1017 | sched_fork(p, clone_flags); | ||
1018 | |||
1017 | /* Need tasklist lock for parent etc handling! */ | 1019 | /* Need tasklist lock for parent etc handling! */ |
1018 | write_lock_irq(&tasklist_lock); | 1020 | write_lock_irq(&tasklist_lock); |
1019 | 1021 | ||
1020 | /* | 1022 | /* |
1021 | * The task hasn't been attached yet, so cpus_allowed mask cannot | 1023 | * The task hasn't been attached yet, so its cpus_allowed mask will |
1022 | * have changed. The cpus_allowed mask of the parent may have | 1024 | * not be changed, nor will its assigned CPU. |
1023 | * changed after it was copied first time, and it may then move to | 1025 | * |
1024 | * another CPU - so we re-copy it here and set the child's CPU to | 1026 | * The cpus_allowed mask of the parent may have changed after it was |
1025 | * the parent's CPU. This avoids alot of nasty races. | 1027 | * copied first time - so re-copy it here, then check the child's CPU |
1028 | * to ensure it is on a valid CPU (and if not, just force it back to | ||
1029 | * parent's CPU). This avoids alot of nasty races. | ||
1026 | */ | 1030 | */ |
1027 | p->cpus_allowed = current->cpus_allowed; | 1031 | p->cpus_allowed = current->cpus_allowed; |
1028 | set_task_cpu(p, smp_processor_id()); | 1032 | if (unlikely(!cpu_isset(task_cpu(p), p->cpus_allowed))) |
1033 | set_task_cpu(p, smp_processor_id()); | ||
1029 | 1034 | ||
1030 | /* | 1035 | /* |
1031 | * Check for pending SIGKILL! The new thread should not be allowed | 1036 | * Check for pending SIGKILL! The new thread should not be allowed |
@@ -1087,6 +1092,11 @@ static task_t *copy_process(unsigned long clone_flags, | |||
1087 | spin_unlock(¤t->sighand->siglock); | 1092 | spin_unlock(¤t->sighand->siglock); |
1088 | } | 1093 | } |
1089 | 1094 | ||
1095 | /* | ||
1096 | * inherit ioprio | ||
1097 | */ | ||
1098 | p->ioprio = current->ioprio; | ||
1099 | |||
1090 | SET_LINKS(p); | 1100 | SET_LINKS(p); |
1091 | if (unlikely(p->ptrace & PT_PTRACED)) | 1101 | if (unlikely(p->ptrace & PT_PTRACED)) |
1092 | __ptrace_link(p, current->parent); | 1102 | __ptrace_link(p, current->parent); |