diff options
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 53 |
1 files changed, 21 insertions, 32 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 533ce27f4b2c..fb8572a42297 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/profile.h> | 42 | #include <linux/profile.h> |
43 | #include <linux/rmap.h> | 43 | #include <linux/rmap.h> |
44 | #include <linux/acct.h> | 44 | #include <linux/acct.h> |
45 | #include <linux/cn_proc.h> | ||
45 | 46 | ||
46 | #include <asm/pgtable.h> | 47 | #include <asm/pgtable.h> |
47 | #include <asm/pgalloc.h> | 48 | #include <asm/pgalloc.h> |
@@ -170,10 +171,9 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) | |||
170 | return NULL; | 171 | return NULL; |
171 | } | 172 | } |
172 | 173 | ||
173 | *ti = *orig->thread_info; | ||
174 | *tsk = *orig; | 174 | *tsk = *orig; |
175 | tsk->thread_info = ti; | 175 | tsk->thread_info = ti; |
176 | ti->task = tsk; | 176 | setup_thread_stack(tsk, orig); |
177 | 177 | ||
178 | /* One for us, one for whoever does the "release_task()" (usually parent) */ | 178 | /* One for us, one for whoever does the "release_task()" (usually parent) */ |
179 | atomic_set(&tsk->usage,2); | 179 | atomic_set(&tsk->usage,2); |
@@ -182,37 +182,37 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) | |||
182 | } | 182 | } |
183 | 183 | ||
184 | #ifdef CONFIG_MMU | 184 | #ifdef CONFIG_MMU |
185 | static inline int dup_mmap(struct mm_struct * mm, struct mm_struct * oldmm) | 185 | static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) |
186 | { | 186 | { |
187 | struct vm_area_struct * mpnt, *tmp, **pprev; | 187 | struct vm_area_struct *mpnt, *tmp, **pprev; |
188 | struct rb_node **rb_link, *rb_parent; | 188 | struct rb_node **rb_link, *rb_parent; |
189 | int retval; | 189 | int retval; |
190 | unsigned long charge; | 190 | unsigned long charge; |
191 | struct mempolicy *pol; | 191 | struct mempolicy *pol; |
192 | 192 | ||
193 | down_write(&oldmm->mmap_sem); | 193 | down_write(&oldmm->mmap_sem); |
194 | flush_cache_mm(current->mm); | 194 | flush_cache_mm(oldmm); |
195 | down_write(&mm->mmap_sem); | ||
196 | |||
195 | mm->locked_vm = 0; | 197 | mm->locked_vm = 0; |
196 | mm->mmap = NULL; | 198 | mm->mmap = NULL; |
197 | mm->mmap_cache = NULL; | 199 | mm->mmap_cache = NULL; |
198 | mm->free_area_cache = oldmm->mmap_base; | 200 | mm->free_area_cache = oldmm->mmap_base; |
199 | mm->cached_hole_size = ~0UL; | 201 | mm->cached_hole_size = ~0UL; |
200 | mm->map_count = 0; | 202 | mm->map_count = 0; |
201 | set_mm_counter(mm, rss, 0); | ||
202 | set_mm_counter(mm, anon_rss, 0); | ||
203 | cpus_clear(mm->cpu_vm_mask); | 203 | cpus_clear(mm->cpu_vm_mask); |
204 | mm->mm_rb = RB_ROOT; | 204 | mm->mm_rb = RB_ROOT; |
205 | rb_link = &mm->mm_rb.rb_node; | 205 | rb_link = &mm->mm_rb.rb_node; |
206 | rb_parent = NULL; | 206 | rb_parent = NULL; |
207 | pprev = &mm->mmap; | 207 | pprev = &mm->mmap; |
208 | 208 | ||
209 | for (mpnt = current->mm->mmap ; mpnt ; mpnt = mpnt->vm_next) { | 209 | for (mpnt = oldmm->mmap; mpnt; mpnt = mpnt->vm_next) { |
210 | struct file *file; | 210 | struct file *file; |
211 | 211 | ||
212 | if (mpnt->vm_flags & VM_DONTCOPY) { | 212 | if (mpnt->vm_flags & VM_DONTCOPY) { |
213 | long pages = vma_pages(mpnt); | 213 | long pages = vma_pages(mpnt); |
214 | mm->total_vm -= pages; | 214 | mm->total_vm -= pages; |
215 | __vm_stat_account(mm, mpnt->vm_flags, mpnt->vm_file, | 215 | vm_stat_account(mm, mpnt->vm_flags, mpnt->vm_file, |
216 | -pages); | 216 | -pages); |
217 | continue; | 217 | continue; |
218 | } | 218 | } |
@@ -253,12 +253,8 @@ static inline int dup_mmap(struct mm_struct * mm, struct mm_struct * oldmm) | |||
253 | } | 253 | } |
254 | 254 | ||
255 | /* | 255 | /* |
256 | * Link in the new vma and copy the page table entries: | 256 | * Link in the new vma and copy the page table entries. |
257 | * link in first so that swapoff can see swap entries. | ||
258 | * Note that, exceptionally, here the vma is inserted | ||
259 | * without holding mm->mmap_sem. | ||
260 | */ | 257 | */ |
261 | spin_lock(&mm->page_table_lock); | ||
262 | *pprev = tmp; | 258 | *pprev = tmp; |
263 | pprev = &tmp->vm_next; | 259 | pprev = &tmp->vm_next; |
264 | 260 | ||
@@ -267,8 +263,7 @@ static inline int dup_mmap(struct mm_struct * mm, struct mm_struct * oldmm) | |||
267 | rb_parent = &tmp->vm_rb; | 263 | rb_parent = &tmp->vm_rb; |
268 | 264 | ||
269 | mm->map_count++; | 265 | mm->map_count++; |
270 | retval = copy_page_range(mm, current->mm, tmp); | 266 | retval = copy_page_range(mm, oldmm, mpnt); |
271 | spin_unlock(&mm->page_table_lock); | ||
272 | 267 | ||
273 | if (tmp->vm_ops && tmp->vm_ops->open) | 268 | if (tmp->vm_ops && tmp->vm_ops->open) |
274 | tmp->vm_ops->open(tmp); | 269 | tmp->vm_ops->open(tmp); |
@@ -277,9 +272,9 @@ static inline int dup_mmap(struct mm_struct * mm, struct mm_struct * oldmm) | |||
277 | goto out; | 272 | goto out; |
278 | } | 273 | } |
279 | retval = 0; | 274 | retval = 0; |
280 | |||
281 | out: | 275 | out: |
282 | flush_tlb_mm(current->mm); | 276 | up_write(&mm->mmap_sem); |
277 | flush_tlb_mm(oldmm); | ||
283 | up_write(&oldmm->mmap_sem); | 278 | up_write(&oldmm->mmap_sem); |
284 | return retval; | 279 | return retval; |
285 | fail_nomem_policy: | 280 | fail_nomem_policy: |
@@ -323,10 +318,11 @@ static struct mm_struct * mm_init(struct mm_struct * mm) | |||
323 | INIT_LIST_HEAD(&mm->mmlist); | 318 | INIT_LIST_HEAD(&mm->mmlist); |
324 | mm->core_waiters = 0; | 319 | mm->core_waiters = 0; |
325 | mm->nr_ptes = 0; | 320 | mm->nr_ptes = 0; |
321 | set_mm_counter(mm, file_rss, 0); | ||
322 | set_mm_counter(mm, anon_rss, 0); | ||
326 | spin_lock_init(&mm->page_table_lock); | 323 | spin_lock_init(&mm->page_table_lock); |
327 | rwlock_init(&mm->ioctx_list_lock); | 324 | rwlock_init(&mm->ioctx_list_lock); |
328 | mm->ioctx_list = NULL; | 325 | mm->ioctx_list = NULL; |
329 | mm->default_kioctx = (struct kioctx)INIT_KIOCTX(mm->default_kioctx, *mm); | ||
330 | mm->free_area_cache = TASK_UNMAPPED_BASE; | 326 | mm->free_area_cache = TASK_UNMAPPED_BASE; |
331 | mm->cached_hole_size = ~0UL; | 327 | mm->cached_hole_size = ~0UL; |
332 | 328 | ||
@@ -472,13 +468,6 @@ static int copy_mm(unsigned long clone_flags, struct task_struct * tsk) | |||
472 | if (clone_flags & CLONE_VM) { | 468 | if (clone_flags & CLONE_VM) { |
473 | atomic_inc(&oldmm->mm_users); | 469 | atomic_inc(&oldmm->mm_users); |
474 | mm = oldmm; | 470 | mm = oldmm; |
475 | /* | ||
476 | * There are cases where the PTL is held to ensure no | ||
477 | * new threads start up in user mode using an mm, which | ||
478 | * allows optimizing out ipis; the tlb_gather_mmu code | ||
479 | * is an example. | ||
480 | */ | ||
481 | spin_unlock_wait(&oldmm->page_table_lock); | ||
482 | goto good_mm; | 471 | goto good_mm; |
483 | } | 472 | } |
484 | 473 | ||
@@ -499,7 +488,7 @@ static int copy_mm(unsigned long clone_flags, struct task_struct * tsk) | |||
499 | if (retval) | 488 | if (retval) |
500 | goto free_pt; | 489 | goto free_pt; |
501 | 490 | ||
502 | mm->hiwater_rss = get_mm_counter(mm,rss); | 491 | mm->hiwater_rss = get_mm_rss(mm); |
503 | mm->hiwater_vm = mm->total_vm; | 492 | mm->hiwater_vm = mm->total_vm; |
504 | 493 | ||
505 | good_mm: | 494 | good_mm: |
@@ -848,7 +837,7 @@ static inline void copy_flags(unsigned long clone_flags, struct task_struct *p) | |||
848 | { | 837 | { |
849 | unsigned long new_flags = p->flags; | 838 | unsigned long new_flags = p->flags; |
850 | 839 | ||
851 | new_flags &= ~PF_SUPERPRIV; | 840 | new_flags &= ~(PF_SUPERPRIV | PF_NOFREEZE); |
852 | new_flags |= PF_FORKNOEXEC; | 841 | new_flags |= PF_FORKNOEXEC; |
853 | if (!(clone_flags & CLONE_PTRACE)) | 842 | if (!(clone_flags & CLONE_PTRACE)) |
854 | p->ptrace = 0; | 843 | p->ptrace = 0; |
@@ -928,7 +917,7 @@ static task_t *copy_process(unsigned long clone_flags, | |||
928 | if (nr_threads >= max_threads) | 917 | if (nr_threads >= max_threads) |
929 | goto bad_fork_cleanup_count; | 918 | goto bad_fork_cleanup_count; |
930 | 919 | ||
931 | if (!try_module_get(p->thread_info->exec_domain->module)) | 920 | if (!try_module_get(task_thread_info(p)->exec_domain->module)) |
932 | goto bad_fork_cleanup_count; | 921 | goto bad_fork_cleanup_count; |
933 | 922 | ||
934 | if (p->binfmt && !try_module_get(p->binfmt->module)) | 923 | if (p->binfmt && !try_module_get(p->binfmt->module)) |
@@ -1135,8 +1124,6 @@ static task_t *copy_process(unsigned long clone_flags, | |||
1135 | if (unlikely(p->ptrace & PT_PTRACED)) | 1124 | if (unlikely(p->ptrace & PT_PTRACED)) |
1136 | __ptrace_link(p, current->parent); | 1125 | __ptrace_link(p, current->parent); |
1137 | 1126 | ||
1138 | cpuset_fork(p); | ||
1139 | |||
1140 | attach_pid(p, PIDTYPE_PID, p->pid); | 1127 | attach_pid(p, PIDTYPE_PID, p->pid); |
1141 | attach_pid(p, PIDTYPE_TGID, p->tgid); | 1128 | attach_pid(p, PIDTYPE_TGID, p->tgid); |
1142 | if (thread_group_leader(p)) { | 1129 | if (thread_group_leader(p)) { |
@@ -1152,6 +1139,8 @@ static task_t *copy_process(unsigned long clone_flags, | |||
1152 | nr_threads++; | 1139 | nr_threads++; |
1153 | total_forks++; | 1140 | total_forks++; |
1154 | write_unlock_irq(&tasklist_lock); | 1141 | write_unlock_irq(&tasklist_lock); |
1142 | proc_fork_connector(p); | ||
1143 | cpuset_fork(p); | ||
1155 | retval = 0; | 1144 | retval = 0; |
1156 | 1145 | ||
1157 | fork_out: | 1146 | fork_out: |
@@ -1188,7 +1177,7 @@ bad_fork_cleanup: | |||
1188 | if (p->binfmt) | 1177 | if (p->binfmt) |
1189 | module_put(p->binfmt->module); | 1178 | module_put(p->binfmt->module); |
1190 | bad_fork_cleanup_put_domain: | 1179 | bad_fork_cleanup_put_domain: |
1191 | module_put(p->thread_info->exec_domain->module); | 1180 | module_put(task_thread_info(p)->exec_domain->module); |
1192 | bad_fork_cleanup_count: | 1181 | bad_fork_cleanup_count: |
1193 | put_group_info(p->group_info); | 1182 | put_group_info(p->group_info); |
1194 | atomic_dec(&p->user->processes); | 1183 | atomic_dec(&p->user->processes); |