lib: add support for LZ4-compressed kernel
[linux-drm-fsl-dcu.git] / kernel / fork.c
index 987b28a1f01b6c6ce5d554eb22d9c89e1cde1e7b..6e6a1c11b3e5939bda764882801a5dd28e904f30 100644 (file)
@@ -1121,6 +1121,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 +1205,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 +1360,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 +1395,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 +1416,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 +1452,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(&current->signal->live);
-               atomic_inc(&current->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 +1467,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(&current->signal->live);
+                       atomic_inc(&current->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++;
        }