diff options
Diffstat (limited to 'kernel/fork.c')
| -rw-r--r-- | kernel/fork.c | 37 | 
1 files changed, 14 insertions, 23 deletions
| diff --git a/kernel/fork.c b/kernel/fork.c index 202a0ba63d3c..b0ec34abc0bb 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -86,6 +86,7 @@ int max_threads;		/* tunable limit on nr_threads */  DEFINE_PER_CPU(unsigned long, process_counts) = 0;  __cacheline_aligned DEFINE_RWLOCK(tasklist_lock);  /* outer */ +EXPORT_SYMBOL_GPL(tasklist_lock);  int nr_processes(void)  { @@ -328,15 +329,17 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)  		if (!tmp)  			goto fail_nomem;  		*tmp = *mpnt; +		INIT_LIST_HEAD(&tmp->anon_vma_chain);  		pol = mpol_dup(vma_policy(mpnt));  		retval = PTR_ERR(pol);  		if (IS_ERR(pol))  			goto fail_nomem_policy;  		vma_set_policy(tmp, pol); +		if (anon_vma_fork(tmp, mpnt)) +			goto fail_nomem_anon_vma_fork;  		tmp->vm_flags &= ~VM_LOCKED;  		tmp->vm_mm = mm;  		tmp->vm_next = NULL; -		anon_vma_link(tmp);  		file = tmp->vm_file;  		if (file) {  			struct inode *inode = file->f_path.dentry->d_inode; @@ -391,6 +394,8 @@ out:  	flush_tlb_mm(oldmm);  	up_write(&oldmm->mmap_sem);  	return retval; +fail_nomem_anon_vma_fork: +	mpol_put(pol);  fail_nomem_policy:  	kmem_cache_free(vm_area_cachep, tmp);  fail_nomem: @@ -454,8 +459,7 @@ static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p)  		(current->mm->flags & MMF_INIT_MASK) : default_dump_filter;  	mm->core_state = NULL;  	mm->nr_ptes = 0; -	set_mm_counter(mm, file_rss, 0); -	set_mm_counter(mm, anon_rss, 0); +	memset(&mm->rss_stat, 0, sizeof(mm->rss_stat));  	spin_lock_init(&mm->page_table_lock);  	mm->free_area_cache = TASK_UNMAPPED_BASE;  	mm->cached_hole_size = ~0UL; @@ -824,6 +828,8 @@ void __cleanup_sighand(struct sighand_struct *sighand)   */  static void posix_cpu_timers_init_group(struct signal_struct *sig)  { +	unsigned long cpu_limit; +  	/* Thread group counters. */  	thread_group_cputime_init(sig); @@ -838,9 +844,9 @@ static void posix_cpu_timers_init_group(struct signal_struct *sig)  	sig->cputime_expires.virt_exp = cputime_zero;  	sig->cputime_expires.sched_exp = 0; -	if (sig->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) { -		sig->cputime_expires.prof_exp = -			secs_to_cputime(sig->rlim[RLIMIT_CPU].rlim_cur); +	cpu_limit = ACCESS_ONCE(sig->rlim[RLIMIT_CPU].rlim_cur); +	if (cpu_limit != RLIM_INFINITY) { +		sig->cputime_expires.prof_exp = secs_to_cputime(cpu_limit);  		sig->cputimer.running = 1;  	} @@ -1033,7 +1039,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,  #endif  	retval = -EAGAIN;  	if (atomic_read(&p->real_cred->user->processes) >= -			p->signal->rlim[RLIMIT_NPROC].rlim_cur) { +			task_rlimit(p, RLIMIT_NPROC)) {  		if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&  		    p->real_cred->user != INIT_USER)  			goto bad_fork_free; @@ -1241,21 +1247,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,  	/* Need tasklist lock for parent etc handling! */  	write_lock_irq(&tasklist_lock); -	/* -	 * The task hasn't been attached yet, so its cpus_allowed mask will -	 * not be changed, nor will its assigned CPU. -	 * -	 * The cpus_allowed mask of the parent may have changed after it was -	 * copied first time - so re-copy it here, then check the child's CPU -	 * to ensure it is on a valid CPU (and if not, just force it back to -	 * parent's CPU). This avoids alot of nasty races. -	 */ -	p->cpus_allowed = current->cpus_allowed; -	p->rt.nr_cpus_allowed = current->rt.nr_cpus_allowed; -	if (unlikely(!cpu_isset(task_cpu(p), p->cpus_allowed) || -			!cpu_online(task_cpu(p)))) -		set_task_cpu(p, smp_processor_id()); -  	/* CLONE_PARENT re-uses the old parent */  	if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) {  		p->real_parent = current->real_parent; @@ -1291,7 +1282,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,  	}  	if (likely(p->pid)) { -		list_add_tail(&p->sibling, &p->real_parent->children);  		tracehook_finish_clone(p, clone_flags, trace);  		if (thread_group_leader(p)) { @@ -1303,6 +1293,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,  			p->signal->tty = tty_kref_get(current->signal->tty);  			attach_pid(p, PIDTYPE_PGID, task_pgrp(current));  			attach_pid(p, PIDTYPE_SID, task_session(current)); +			list_add_tail(&p->sibling, &p->real_parent->children);  			list_add_tail_rcu(&p->tasks, &init_task.tasks);  			__get_cpu_var(process_counts)++;  		} | 
