Allow guest to specify syscall vector to use.
[pandora-kernel.git] / kernel / exit.c
index 2c704c8..f1aec27 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/taskstats_kern.h>
 #include <linux/delayacct.h>
 #include <linux/freezer.h>
-#include <linux/cpuset.h>
+#include <linux/cgroup.h>
 #include <linux/syscalls.h>
 #include <linux/signal.h>
 #include <linux/posix-timers.h>
@@ -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);
 
@@ -221,7 +221,7 @@ static int will_become_orphaned_pgrp(struct pid *pgrp, struct task_struct *ignor
        do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
                if (p == ignored_task
                                || p->exit_state
-                               || is_init(p->real_parent))
+                               || is_global_init(p->real_parent))
                        continue;
                if (task_pgrp(p->real_parent) != pgrp &&
                    task_session(p->real_parent) == task_session(p)) {
@@ -299,14 +299,14 @@ void __set_special_pids(pid_t session, pid_t pgrp)
 {
        struct task_struct *curr = current->group_leader;
 
-       if (process_session(curr) != session) {
+       if (task_session_nr(curr) != session) {
                detach_pid(curr, PIDTYPE_SID);
-               set_signal_session(curr->signal, session);
+               set_task_session(curr, session);
                attach_pid(curr, PIDTYPE_SID, find_pid(session));
        }
-       if (process_group(curr) != 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));
        }
 }
@@ -400,11 +400,12 @@ void daemonize(const char *name, ...)
        current->fs = fs;
        atomic_inc(&fs->count);
 
-       exit_task_namespaces(current);
-       current->nsproxy = init_task.nsproxy;
-       get_task_namespaces(current);
+       if (current->nsproxy != init_task.nsproxy) {
+               get_nsproxy(init_task.nsproxy);
+               switch_task_namespaces(current, init_task.nsproxy);
+       }
 
-       exit_files(current);
+       exit_files(current);
        current->files = init_task.files;
        atomic_inc(&current->files->count);
 
@@ -492,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;
 
@@ -509,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)) {
@@ -530,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;
 
@@ -665,19 +666,22 @@ 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, *reaper = father;
-       struct list_head *_p, *_n;
+       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);
                if (reaper == father) {
-                       reaper = child_reaper(father);
+                       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:
@@ -687,9 +691,8 @@ forget_original_parent(struct task_struct *father, struct list_head *to_release)
         *
         * Search them and reparent children.
         */
-       list_for_each_safe(_p, _n, &father->children) {
+       list_for_each_entry_safe(p, n, &father->children, sibling) {
                int ptrace;
-               p = list_entry(_p, struct task_struct, sibling);
 
                ptrace = p->ptrace;
 
@@ -715,13 +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_safe(_p, _n, &father->ptrace_children) {
-               p = list_entry(_p, struct task_struct, ptrace_list);
+
+       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);
+       }
+
 }
 
 /*
@@ -732,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)
@@ -753,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:
         *
@@ -763,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
@@ -792,7 +800,7 @@ static void exit_notify(struct task_struct *tsk)
        /* Let father know we died
         *
         * Thread signals are configurable, but you aren't going to use
-        * that to send signals to arbitary processes. 
+        * that to send signals to arbitary processes.
         * That stops right now.
         *
         * If the parent exec id doesn't match the exec id we saved
@@ -833,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);
@@ -874,10 +876,35 @@ static inline void check_stack_usage(void) {}
 
 static inline void exit_child_reaper(struct task_struct *tsk)
 {
-       if (likely(tsk->group_leader != child_reaper(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)
@@ -932,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);
@@ -972,7 +999,7 @@ fastcall NORET_TYPE void do_exit(long code)
        __exit_fs(tsk);
        check_stack_usage();
        exit_thread();
-       cpuset_exit(tsk);
+       cgroup_exit(tsk, 1);
        exit_keys(tsk);
 
        if (group_dead && tsk->signal->leader)
@@ -983,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);
@@ -1086,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 (process_group(p) != process_group(current))
+               if (task_pgrp_nr_ns(p, ns) != task_pgrp_vnr(current))
                        return 0;
        } else if (pid != -1) {
-               if (process_group(p) != -pid)
+               if (task_pgrp_nr_ns(p, ns) != -pid)
                        return 0;
        }
 
@@ -1164,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;
@@ -1285,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);
@@ -1326,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;
@@ -1344,11 +1376,12 @@ 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;
 
@@ -1419,11 +1452,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);
@@ -1443,6 +1476,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;
@@ -1457,7 +1491,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);
@@ -1468,7 +1503,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,
@@ -1517,12 +1552,9 @@ repeat:
        tsk = current;
        do {
                struct task_struct *p;
-               struct list_head *_p;
                int ret;
 
-               list_for_each(_p,&tsk->children) {
-                       p = list_entry(_p, struct task_struct, sibling);
-
+               list_for_each_entry(p, &tsk->children, sibling) {
                        ret = eligible_child(pid, options, p);
                        if (!ret)
                                continue;
@@ -1604,9 +1636,8 @@ check_continued:
                        }
                }
                if (!flag) {
-                       list_for_each(_p, &tsk->ptrace_children) {
-                               p = list_entry(_p, struct task_struct,
-                                               ptrace_list);
+                       list_for_each_entry(p, &tsk->ptrace_children,
+                                           ptrace_list) {
                                if (!eligible_child(pid, options, p))
                                        continue;
                                flag = 1;