diff options
Diffstat (limited to 'kernel/fork.c')
| -rw-r--r-- | kernel/fork.c | 78 | 
1 files changed, 44 insertions, 34 deletions
| diff --git a/kernel/fork.c b/kernel/fork.c index 987b28a1f01..e23bb19e2a3 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -365,8 +365,6 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)  	mm->locked_vm = 0;  	mm->mmap = NULL;  	mm->mmap_cache = NULL; -	mm->free_area_cache = oldmm->mmap_base; -	mm->cached_hole_size = ~0UL;  	mm->map_count = 0;  	cpumask_clear(mm_cpumask(mm));  	mm->mm_rb = RB_ROOT; @@ -540,8 +538,6 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p)  	mm->nr_ptes = 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;  	mm_init_aio(mm);  	mm_init_owner(mm, p); @@ -1121,6 +1117,12 @@ static void posix_cpu_timers_init(struct task_struct *tsk)  	INIT_LIST_HEAD(&tsk->cpu_timers[2]);  } +static inline void +init_task_pid(struct task_struct *task, enum pid_type type, struct pid *pid) +{ +	 task->pids[type].pid = pid; +} +  /*   * This creates a new process as a copy of the old one,   * but does not actually start it yet. @@ -1199,8 +1201,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,  	retval = -EAGAIN;  	if (atomic_read(&p->real_cred->user->processes) >=  			task_rlimit(p, RLIMIT_NPROC)) { -		if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) && -		    p->real_cred->user != INIT_USER) +		if (p->real_cred->user != INIT_USER && +		    !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN))  			goto bad_fork_free;  	}  	current->flags &= ~PF_NPROC_EXCEEDED; @@ -1354,11 +1356,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,  			goto bad_fork_cleanup_io;  	} -	p->pid = pid_nr(pid); -	p->tgid = p->pid; -	if (clone_flags & CLONE_THREAD) -		p->tgid = current->tgid; -  	p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;  	/*  	 * Clear TID on mm_release()? @@ -1394,12 +1391,19 @@ static struct task_struct *copy_process(unsigned long clone_flags,  	clear_all_latency_tracing(p);  	/* ok, now we should be set up.. */ -	if (clone_flags & CLONE_THREAD) +	p->pid = pid_nr(pid); +	if (clone_flags & CLONE_THREAD) {  		p->exit_signal = -1; -	else if (clone_flags & CLONE_PARENT) -		p->exit_signal = current->group_leader->exit_signal; -	else -		p->exit_signal = (clone_flags & CSIGNAL); +		p->group_leader = current->group_leader; +		p->tgid = current->tgid; +	} else { +		if (clone_flags & CLONE_PARENT) +			p->exit_signal = current->group_leader->exit_signal; +		else +			p->exit_signal = (clone_flags & CSIGNAL); +		p->group_leader = p; +		p->tgid = p->pid; +	}  	p->pdeath_signal = 0;  	p->exit_state = 0; @@ -1408,15 +1412,13 @@ static struct task_struct *copy_process(unsigned long clone_flags,  	p->nr_dirtied_pause = 128 >> (PAGE_SHIFT - 10);  	p->dirty_paused_when = 0; -	/* -	 * Ok, make it visible to the rest of the system. -	 * We dont wake it up yet. -	 */ -	p->group_leader = p;  	INIT_LIST_HEAD(&p->thread_group);  	p->task_works = NULL; -	/* Need tasklist lock for parent etc handling! */ +	/* +	 * Make it visible to the rest of the system, but dont wake it up yet. +	 * Need tasklist lock for parent etc handling! +	 */  	write_lock_irq(&tasklist_lock);  	/* CLONE_PARENT re-uses the old parent */ @@ -1446,18 +1448,14 @@ static struct task_struct *copy_process(unsigned long clone_flags,  		goto bad_fork_free_pid;  	} -	if (clone_flags & CLONE_THREAD) { -		current->signal->nr_threads++; -		atomic_inc(¤t->signal->live); -		atomic_inc(¤t->signal->sigcnt); -		p->group_leader = current->group_leader; -		list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group); -	} -  	if (likely(p->pid)) {  		ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace); +		init_task_pid(p, PIDTYPE_PID, pid);  		if (thread_group_leader(p)) { +			init_task_pid(p, PIDTYPE_PGID, task_pgrp(current)); +			init_task_pid(p, PIDTYPE_SID, task_session(current)); +  			if (is_child_reaper(pid)) {  				ns_of_pid(pid)->child_reaper = p;  				p->signal->flags |= SIGNAL_UNKILLABLE; @@ -1465,13 +1463,19 @@ static struct task_struct *copy_process(unsigned long clone_flags,  			p->signal->leader_pid = pid;  			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); +			attach_pid(p, PIDTYPE_PGID); +			attach_pid(p, PIDTYPE_SID);  			__this_cpu_inc(process_counts); +		} else { +			current->signal->nr_threads++; +			atomic_inc(¤t->signal->live); +			atomic_inc(¤t->signal->sigcnt); +			list_add_tail_rcu(&p->thread_group, +					  &p->group_leader->thread_group);  		} -		attach_pid(p, PIDTYPE_PID, pid); +		attach_pid(p, PIDTYPE_PID);  		nr_threads++;  	} @@ -1542,7 +1546,7 @@ static inline void init_idle_pids(struct pid_link *links)  	}  } -struct task_struct * __cpuinit fork_idle(int cpu) +struct task_struct *fork_idle(int cpu)  {  	struct task_struct *task;  	task = copy_process(CLONE_VM, 0, 0, NULL, &init_struct_pid, 0); @@ -1675,6 +1679,12 @@ SYSCALL_DEFINE5(clone, unsigned long, newsp, unsigned long, clone_flags,  		 int __user *, parent_tidptr,  		 int __user *, child_tidptr,  		 int, tls_val) +#elif defined(CONFIG_CLONE_BACKWARDS3) +SYSCALL_DEFINE6(clone, unsigned long, clone_flags, unsigned long, newsp, +		int, stack_size, +		int __user *, parent_tidptr, +		int __user *, child_tidptr, +		int, tls_val)  #else  SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,  		 int __user *, parent_tidptr, | 
