Merge branch 'fixes' of git://git.linaro.org/people/rmk/linux-arm
[linux-flexiantxendom0-3.2.10.git] / kernel / exit.c
index 73bb192..d8bd3b4 100644 (file)
@@ -51,6 +51,8 @@
 #include <trace/events/sched.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/oom.h>
+#include <linux/writeback.h>
+#include <linux/shm.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -85,7 +87,6 @@ static void __exit_signal(struct task_struct *tsk)
        struct tty_struct *uninitialized_var(tty);
 
        sighand = rcu_dereference_check(tsk->sighand,
-                                       rcu_read_lock_held() ||
                                        lockdep_tasklist_lock_is_held());
        spin_lock(&sighand->siglock);
 
@@ -122,9 +123,9 @@ static void __exit_signal(struct task_struct *tsk)
                 * We won't ever get here for the group leader, since it
                 * will have been the last reference on the signal_struct.
                 */
-               sig->utime = cputime_add(sig->utime, tsk->utime);
-               sig->stime = cputime_add(sig->stime, tsk->stime);
-               sig->gtime = cputime_add(sig->gtime, tsk->gtime);
+               sig->utime += tsk->utime;
+               sig->stime += tsk->stime;
+               sig->gtime += tsk->gtime;
                sig->min_flt += tsk->min_flt;
                sig->maj_flt += tsk->maj_flt;
                sig->nvcsw += tsk->nvcsw;
@@ -424,7 +425,7 @@ void daemonize(const char *name, ...)
         */
        exit_mm(current);
        /*
-        * We don't want to have TIF_FREEZE set if the system-wide hibernation
+        * We don't want to get frozen, in case system-wide hibernation
         * or suspend transition begins right now.
         */
        current->flags |= (PF_NOFREEZE | PF_KTHREAD);
@@ -473,7 +474,7 @@ static void close_files(struct files_struct * files)
                i = j * __NFDBITS;
                if (i >= fdt->max_fds)
                        break;
-               set = fdt->open_fds->fds_bits[j++];
+               set = fdt->open_fds[j++];
                while (set) {
                        if (set & 1) {
                                struct file * file = xchg(&fdt->fd[i], NULL);
@@ -680,21 +681,17 @@ static void exit_mm(struct task_struct * tsk)
        tsk->mm = NULL;
        up_read(&mm->mmap_sem);
        enter_lazy_tlb(mm, current);
-       /* We don't want this task to be frozen prematurely */
-       clear_freeze_flag(tsk);
-       if (tsk->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
-               atomic_dec(&mm->oom_disable_count);
        task_unlock(tsk);
        mm_update_next_owner(mm);
        mmput(mm);
 }
 
 /*
- * When we die, we re-parent all our children.
- * Try to give them to another thread in our thread
- * group, and if no such member exists, give it to
- * the child reaper process (ie "init") in our pid
- * space.
+ * When we die, we re-parent all our children, and try to:
+ * 1. give them to another thread in our thread group, if such a member exists
+ * 2. give it to the first ancestor process which prctl'd itself as a
+ *    child_subreaper for its children (like a service manager)
+ * 3. give it to the init process (PID 1) in our pid namespace
  */
 static struct task_struct *find_new_reaper(struct task_struct *father)
        __releases(&tasklist_lock)
@@ -714,8 +711,11 @@ static struct task_struct *find_new_reaper(struct task_struct *father)
 
        if (unlikely(pid_ns->child_reaper == father)) {
                write_unlock_irq(&tasklist_lock);
-               if (unlikely(pid_ns == &init_pid_ns))
-                       panic("Attempted to kill init!");
+               if (unlikely(pid_ns == &init_pid_ns)) {
+                       panic("Attempted to kill init! exitcode=0x%08x\n",
+                               father->signal->group_exit_code ?:
+                                       father->exit_code);
+               }
 
                zap_pid_ns_processes(pid_ns);
                write_lock_irq(&tasklist_lock);
@@ -725,6 +725,29 @@ static struct task_struct *find_new_reaper(struct task_struct *father)
                 * forget_original_parent() must move them somewhere.
                 */
                pid_ns->child_reaper = init_pid_ns.child_reaper;
+       } else if (father->signal->has_child_subreaper) {
+               struct task_struct *reaper;
+
+               /*
+                * Find the first ancestor marked as child_subreaper.
+                * Note that the code below checks same_thread_group(reaper,
+                * pid_ns->child_reaper).  This is what we need to DTRT in a
+                * PID namespace. However we still need the check above, see
+                * http://marc.info/?l=linux-kernel&m=131385460420380
+                */
+               for (reaper = father->real_parent;
+                    reaper != &init_task;
+                    reaper = reaper->real_parent) {
+                       if (same_thread_group(reaper, pid_ns->child_reaper))
+                               break;
+                       if (!reaper->signal->is_child_subreaper)
+                               continue;
+                       thread = reaper;
+                       do {
+                               if (!(thread->flags & PF_EXITING))
+                                       return reaper;
+                       } while_each_thread(reaper, thread);
+               }
        }
 
        return pid_ns->child_reaper;
@@ -822,25 +845,6 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
        if (group_dead)
                kill_orphaned_pgrp(tsk->group_leader, NULL);
 
-       /* Let father know we died
-        *
-        * Thread signals are configurable, but you aren't going to use
-        * that to send signals to arbitrary processes.
-        * That stops right now.
-        *
-        * If the parent exec id doesn't match the exec id we saved
-        * when we started then we know the parent has changed security
-        * domain.
-        *
-        * If our self_exec id doesn't match our parent_exec_id then
-        * we have changed execution domain as these two values started
-        * the same after a fork.
-        */
-       if (thread_group_leader(tsk) && tsk->exit_signal != SIGCHLD &&
-           (tsk->parent_exec_id != tsk->real_parent->self_exec_id ||
-            tsk->self_exec_id != tsk->parent_exec_id))
-               tsk->exit_signal = SIGCHLD;
-
        if (unlikely(tsk->ptrace)) {
                int sig = thread_group_leader(tsk) &&
                                thread_group_empty(tsk) &&
@@ -891,14 +895,13 @@ static void check_stack_usage(void)
 static inline void check_stack_usage(void) {}
 #endif
 
-NORET_TYPE void do_exit(long code)
+void do_exit(long code)
 {
        struct task_struct *tsk = current;
        int group_dead;
 
        profile_task_exit(tsk);
 
-       WARN_ON(atomic_read(&tsk->fs_excl));
        WARN_ON(blk_needs_flush_plug(tsk));
 
        if (unlikely(in_interrupt()))
@@ -940,8 +943,6 @@ NORET_TYPE void do_exit(long code)
                schedule();
        }
 
-       exit_irq_thread();
-
        exit_signals(tsk);  /* sets PF_EXITING */
        /*
         * tsk->flags are checked in the futex code to protect against
@@ -950,6 +951,8 @@ NORET_TYPE void do_exit(long code)
        smp_mb();
        raw_spin_unlock_wait(&tsk->pi_lock);
 
+       exit_irq_thread();
+
        if (unlikely(in_atomic()))
                printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n",
                                current->comm, task_pid_nr(current),
@@ -958,7 +961,7 @@ NORET_TYPE void do_exit(long code)
        acct_update_integrals(tsk);
        /* sync mm's RSS info before statistics gathering */
        if (tsk->mm)
-               sync_mm_rss(tsk, tsk->mm);
+               sync_mm_rss(tsk->mm);
        group_dead = atomic_dec_and_test(&tsk->signal->live);
        if (group_dead) {
                hrtimer_cancel(&tsk->signal->real_timer);
@@ -969,8 +972,7 @@ NORET_TYPE void do_exit(long code)
        acct_collect(code, group_dead);
        if (group_dead)
                tty_audit_exit();
-       if (unlikely(tsk->audit_context))
-               audit_free(tsk);
+       audit_free(tsk);
 
        tsk->exit_code = code;
        taskstats_exit(tsk, group_dead);
@@ -982,6 +984,7 @@ NORET_TYPE void do_exit(long code)
        trace_sched_process_exit(tsk);
 
        exit_sem(tsk);
+       exit_shm(tsk);
        exit_files(tsk);
        exit_fs(tsk);
        check_stack_usage();
@@ -1040,9 +1043,28 @@ NORET_TYPE void do_exit(long code)
        validate_creds_for_do_exit(tsk);
 
        preempt_disable();
+       if (tsk->nr_dirtied)
+               __this_cpu_add(dirty_throttle_leaks, tsk->nr_dirtied);
        exit_rcu();
+
+       /*
+        * The setting of TASK_RUNNING by try_to_wake_up() may be delayed
+        * when the following two conditions become true.
+        *   - There is race condition of mmap_sem (It is acquired by
+        *     exit_mm()), and
+        *   - SMI occurs before setting TASK_RUNINNG.
+        *     (or hypervisor of virtual machine switches to other guest)
+        *  As a result, we may become TASK_RUNNING after becoming TASK_DEAD
+        *
+        * To avoid it, we have to wait for releasing tsk->pi_lock which
+        * is held by try_to_wake_up()
+        */
+       smp_mb();
+       raw_spin_unlock_wait(&tsk->pi_lock);
+
        /* causes final put_task_struct in finish_task_switch(). */
        tsk->state = TASK_DEAD;
+       tsk->flags |= PF_NOFREEZE;      /* tell freezer to ignore us */
        schedule();
        BUG();
        /* Avoid "noreturn function does return".  */
@@ -1052,7 +1074,7 @@ NORET_TYPE void do_exit(long code)
 
 EXPORT_SYMBOL_GPL(do_exit);
 
-NORET_TYPE void complete_and_exit(struct completion *comp, long code)
+void complete_and_exit(struct completion *comp, long code)
 {
        if (comp)
                complete(comp);
@@ -1071,7 +1093,7 @@ SYSCALL_DEFINE1(exit, int, error_code)
  * Take down every thread in the group.  This is called by fatal signals
  * as well as by sys_exit_group (below).
  */
-NORET_TYPE void
+void
 do_group_exit(int exit_code)
 {
        struct signal_struct *sig = current->signal;
@@ -1258,19 +1280,9 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
                spin_lock_irq(&p->real_parent->sighand->siglock);
                psig = p->real_parent->signal;
                sig = p->signal;
-               psig->cutime =
-                       cputime_add(psig->cutime,
-                       cputime_add(tgutime,
-                                   sig->cutime));
-               psig->cstime =
-                       cputime_add(psig->cstime,
-                       cputime_add(tgstime,
-                                   sig->cstime));
-               psig->cgtime =
-                       cputime_add(psig->cgtime,
-                       cputime_add(p->gtime,
-                       cputime_add(sig->gtime,
-                                   sig->cgtime)));
+               psig->cutime += tgutime + sig->cutime;
+               psig->cstime += tgstime + sig->cstime;
+               psig->cgtime += p->gtime + sig->gtime + sig->cgtime;
                psig->cmin_flt +=
                        p->min_flt + sig->min_flt + sig->cmin_flt;
                psig->cmaj_flt +=
@@ -1543,8 +1555,15 @@ static int wait_consider_task(struct wait_opts *wo, int ptrace,
        }
 
        /* dead body doesn't have much to contribute */
-       if (p->exit_state == EXIT_DEAD)
+       if (unlikely(p->exit_state == EXIT_DEAD)) {
+               /*
+                * But do not ignore this task until the tracer does
+                * wait_task_zombie()->do_notify_parent().
+                */
+               if (likely(!ptrace) && unlikely(ptrace_reparented(p)))
+                       wo->notask_error = 0;
                return 0;
+       }
 
        /* slay zombie? */
        if (p->exit_state == EXIT_ZOMBIE) {