]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - kernel/exit.c
Blackfin arch: add defines for the on-chip L1 ROM of BF54x
[linux-2.6-omap-h63xx.git] / kernel / exit.c
index 179ac74bf9115c4f6889b1b03b4ee3fdfc96482a..cd0f1d4137a734abb393a5ebc5a8534b2b8f882a 100644 (file)
@@ -148,6 +148,7 @@ void release_task(struct task_struct * p)
        int zap_leader;
 repeat:
        atomic_dec(&p->user->processes);
+       proc_flush_task(p);
        write_lock_irq(&tasklist_lock);
        ptrace_unlink(p);
        BUG_ON(!list_empty(&p->ptrace_list) || !list_empty(&p->ptrace_children));
@@ -175,7 +176,6 @@ repeat:
        }
 
        write_unlock_irq(&tasklist_lock);
-       proc_flush_task(p);
        release_thread(p);
        call_rcu(&p->rcu, delayed_put_task_struct);
 
@@ -306,7 +306,7 @@ void __set_special_pids(pid_t session, pid_t pgrp)
        }
        if (task_pgrp_nr(curr) != pgrp) {
                detach_pid(curr, PIDTYPE_PGID);
-               curr->signal->pgrp = pgrp;
+               set_task_pgrp(curr, pgrp);
                attach_pid(curr, PIDTYPE_PGID, find_pid(pgrp));
        }
 }
@@ -493,7 +493,7 @@ void reset_files_struct(struct task_struct *tsk, struct files_struct *files)
 }
 EXPORT_SYMBOL(reset_files_struct);
 
-static inline void __exit_files(struct task_struct *tsk)
+static void __exit_files(struct task_struct *tsk)
 {
        struct files_struct * files = tsk->files;
 
@@ -510,7 +510,7 @@ void exit_files(struct task_struct *tsk)
        __exit_files(tsk);
 }
 
-static inline void __put_fs_struct(struct fs_struct *fs)
+static void __put_fs_struct(struct fs_struct *fs)
 {
        /* No need to hold fs->lock if we are killing it */
        if (atomic_dec_and_test(&fs->count)) {
@@ -531,7 +531,7 @@ void put_fs_struct(struct fs_struct *fs)
        __put_fs_struct(fs);
 }
 
-static inline void __exit_fs(struct task_struct *tsk)
+static void __exit_fs(struct task_struct *tsk)
 {
        struct fs_struct * fs = tsk->fs;
 
@@ -666,10 +666,14 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
  * the child reaper process (ie "init") in our pid
  * space.
  */
-static void
-forget_original_parent(struct task_struct *father, struct list_head *to_release)
+static void forget_original_parent(struct task_struct *father)
 {
        struct task_struct *p, *n, *reaper = father;
+       struct list_head ptrace_dead;
+
+       INIT_LIST_HEAD(&ptrace_dead);
+
+       write_lock_irq(&tasklist_lock);
 
        do {
                reaper = next_thread(reaper);
@@ -677,7 +681,7 @@ forget_original_parent(struct task_struct *father, struct list_head *to_release)
                        reaper = task_child_reaper(father);
                        break;
                }
-       } while (reaper->exit_state);
+       } while (reaper->flags & PF_EXITING);
 
        /*
         * There are only two places where our children can be:
@@ -714,12 +718,23 @@ forget_original_parent(struct task_struct *father, struct list_head *to_release)
                 * while it was being traced by us, to be able to see it in wait4.
                 */
                if (unlikely(ptrace && p->exit_state == EXIT_ZOMBIE && p->exit_signal == -1))
-                       list_add(&p->ptrace_list, to_release);
+                       list_add(&p->ptrace_list, &ptrace_dead);
        }
+
        list_for_each_entry_safe(p, n, &father->ptrace_children, ptrace_list) {
                p->real_parent = reaper;
                reparent_thread(p, father, 1);
        }
+
+       write_unlock_irq(&tasklist_lock);
+       BUG_ON(!list_empty(&father->children));
+       BUG_ON(!list_empty(&father->ptrace_children));
+
+       list_for_each_entry_safe(p, n, &ptrace_dead, ptrace_list) {
+               list_del_init(&p->ptrace_list);
+               release_task(p);
+       }
+
 }
 
 /*
@@ -730,7 +745,6 @@ static void exit_notify(struct task_struct *tsk)
 {
        int state;
        struct task_struct *t;
-       struct list_head ptrace_dead, *_p, *_n;
        struct pid *pgrp;
 
        if (signal_pending(tsk) && !(tsk->signal->flags & SIGNAL_GROUP_EXIT)
@@ -751,8 +765,6 @@ static void exit_notify(struct task_struct *tsk)
                spin_unlock_irq(&tsk->sighand->siglock);
        }
 
-       write_lock_irq(&tasklist_lock);
-
        /*
         * This does two things:
         *
@@ -761,12 +773,10 @@ static void exit_notify(struct task_struct *tsk)
         *      as a result of our exiting, and if they have any stopped
         *      jobs, send them a SIGHUP and then a SIGCONT.  (POSIX 3.2.2.2)
         */
+       forget_original_parent(tsk);
+       exit_task_namespaces(tsk);
 
-       INIT_LIST_HEAD(&ptrace_dead);
-       forget_original_parent(tsk, &ptrace_dead);
-       BUG_ON(!list_empty(&tsk->children));
-       BUG_ON(!list_empty(&tsk->ptrace_children));
-
+       write_lock_irq(&tasklist_lock);
        /*
         * Check to see if any process groups have become orphaned
         * as a result of our exiting, and if they have any stopped
@@ -831,12 +841,6 @@ static void exit_notify(struct task_struct *tsk)
 
        write_unlock_irq(&tasklist_lock);
 
-       list_for_each_safe(_p, _n, &ptrace_dead) {
-               list_del_init(_p);
-               t = list_entry(_p, struct task_struct, ptrace_list);
-               release_task(t);
-       }
-
        /* If the process is dead, release it - nobody will wait for it */
        if (state == EXIT_DEAD)
                release_task(tsk);
@@ -875,7 +879,32 @@ static inline void exit_child_reaper(struct task_struct *tsk)
        if (likely(tsk->group_leader != task_child_reaper(tsk)))
                return;
 
-       panic("Attempted to kill init!");
+       if (tsk->nsproxy->pid_ns == &init_pid_ns)
+               panic("Attempted to kill init!");
+
+       /*
+        * @tsk is the last thread in the 'cgroup-init' and is exiting.
+        * Terminate all remaining processes in the namespace and reap them
+        * before exiting @tsk.
+        *
+        * Note that @tsk (last thread of cgroup-init) may not necessarily
+        * be the child-reaper (i.e main thread of cgroup-init) of the
+        * namespace i.e the child_reaper may have already exited.
+        *
+        * Even after a child_reaper exits, we let it inherit orphaned children,
+        * because, pid_ns->child_reaper remains valid as long as there is
+        * at least one living sub-thread in the cgroup init.
+
+        * This living sub-thread of the cgroup-init will be notified when
+        * a child inherited by the 'child-reaper' exits (do_notify_parent()
+        * uses __group_send_sig_info()). Further, when reaping child processes,
+        * do_wait() iterates over children of all living sub threads.
+
+        * i.e even though 'child_reaper' thread is listed as the parent of the
+        * orphaned children, any living sub-thread in the cgroup-init can
+        * perform the role of the child_reaper.
+        */
+       zap_pid_ns_processes(tsk->nsproxy->pid_ns);
 }
 
 fastcall NORET_TYPE void do_exit(long code)
@@ -930,7 +959,7 @@ fastcall NORET_TYPE void do_exit(long code)
 
        if (unlikely(in_atomic()))
                printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n",
-                               current->comm, current->pid,
+                               current->comm, task_pid_nr(current),
                                preempt_count());
 
        acct_update_integrals(tsk);
@@ -981,7 +1010,6 @@ fastcall NORET_TYPE void do_exit(long code)
                module_put(tsk->binfmt->module);
 
        proc_exit_connector(tsk);
-       exit_task_namespaces(tsk);
        exit_notify(tsk);
 #ifdef CONFIG_NUMA
        mpol_free(tsk->mempolicy);
@@ -1084,15 +1112,17 @@ asmlinkage void sys_exit_group(int error_code)
 static int eligible_child(pid_t pid, int options, struct task_struct *p)
 {
        int err;
+       struct pid_namespace *ns;
 
+       ns = current->nsproxy->pid_ns;
        if (pid > 0) {
-               if (p->pid != pid)
+               if (task_pid_nr_ns(p, ns) != pid)
                        return 0;
        } else if (!pid) {
-               if (task_pgrp_nr(p) != task_pgrp_nr(current))
+               if (task_pgrp_nr_ns(p, ns) != task_pgrp_vnr(current))
                        return 0;
        } else if (pid != -1) {
-               if (task_pgrp_nr(p) != -pid)
+               if (task_pgrp_nr_ns(p, ns) != -pid)
                        return 0;
        }
 
@@ -1162,9 +1192,12 @@ static int wait_task_zombie(struct task_struct *p, int noreap,
 {
        unsigned long state;
        int retval, status, traced;
+       struct pid_namespace *ns;
+
+       ns = current->nsproxy->pid_ns;
 
        if (unlikely(noreap)) {
-               pid_t pid = p->pid;
+               pid_t pid = task_pid_nr_ns(p, ns);
                uid_t uid = p->uid;
                int exit_code = p->exit_code;
                int why, status;
@@ -1283,11 +1316,11 @@ static int wait_task_zombie(struct task_struct *p, int noreap,
                        retval = put_user(status, &infop->si_status);
        }
        if (!retval && infop)
-               retval = put_user(p->pid, &infop->si_pid);
+               retval = put_user(task_pid_nr_ns(p, ns), &infop->si_pid);
        if (!retval && infop)
                retval = put_user(p->uid, &infop->si_uid);
        if (!retval)
-               retval = p->pid;
+               retval = task_pid_nr_ns(p, ns);
 
        if (traced) {
                write_lock_irq(&tasklist_lock);
@@ -1324,6 +1357,7 @@ static int wait_task_stopped(struct task_struct *p, int delayed_group_leader,
                             int __user *stat_addr, struct rusage __user *ru)
 {
        int retval, exit_code;
+       struct pid_namespace *ns;
 
        if (!p->exit_code)
                return 0;
@@ -1342,17 +1376,17 @@ static int wait_task_stopped(struct task_struct *p, int delayed_group_leader,
         * keep holding onto the tasklist_lock while we call getrusage and
         * possibly take page faults for user memory.
         */
+       ns = current->nsproxy->pid_ns;
        get_task_struct(p);
        read_unlock(&tasklist_lock);
 
        if (unlikely(noreap)) {
-               pid_t pid = p->pid;
+               pid_t pid = task_pid_nr_ns(p, ns);
                uid_t uid = p->uid;
                int why = (p->ptrace & PT_PTRACED) ? CLD_TRAPPED : CLD_STOPPED;
 
                exit_code = p->exit_code;
-               if (unlikely(!exit_code) ||
-                   unlikely(p->state & TASK_TRACED))
+               if (unlikely(!exit_code) || unlikely(p->exit_state))
                        goto bail_ref;
                return wait_noreap_copyout(p, pid, uid,
                                           why, (exit_code << 8) | 0x7f,
@@ -1417,11 +1451,11 @@ bail_ref:
        if (!retval && infop)
                retval = put_user(exit_code, &infop->si_status);
        if (!retval && infop)
-               retval = put_user(p->pid, &infop->si_pid);
+               retval = put_user(task_pid_nr_ns(p, ns), &infop->si_pid);
        if (!retval && infop)
                retval = put_user(p->uid, &infop->si_uid);
        if (!retval)
-               retval = p->pid;
+               retval = task_pid_nr_ns(p, ns);
        put_task_struct(p);
 
        BUG_ON(!retval);
@@ -1441,6 +1475,7 @@ static int wait_task_continued(struct task_struct *p, int noreap,
        int retval;
        pid_t pid;
        uid_t uid;
+       struct pid_namespace *ns;
 
        if (!(p->signal->flags & SIGNAL_STOP_CONTINUED))
                return 0;
@@ -1455,7 +1490,8 @@ static int wait_task_continued(struct task_struct *p, int noreap,
                p->signal->flags &= ~SIGNAL_STOP_CONTINUED;
        spin_unlock_irq(&p->sighand->siglock);
 
-       pid = p->pid;
+       ns = current->nsproxy->pid_ns;
+       pid = task_pid_nr_ns(p, ns);
        uid = p->uid;
        get_task_struct(p);
        read_unlock(&tasklist_lock);
@@ -1466,7 +1502,7 @@ static int wait_task_continued(struct task_struct *p, int noreap,
                if (!retval && stat_addr)
                        retval = put_user(0xffff, stat_addr);
                if (!retval)
-                       retval = p->pid;
+                       retval = task_pid_nr_ns(p, ns);
        } else {
                retval = wait_noreap_copyout(p, pid, uid,
                                             CLD_CONTINUED, SIGCONT,