diff options
Diffstat (limited to 'kernel/exit.c')
-rw-r--r-- | kernel/exit.c | 85 |
1 files changed, 23 insertions, 62 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index ad933bb29ec7..eb4d6470d1d0 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/resource.h> | 46 | #include <linux/resource.h> |
47 | #include <linux/blkdev.h> | 47 | #include <linux/blkdev.h> |
48 | #include <linux/task_io_accounting_ops.h> | 48 | #include <linux/task_io_accounting_ops.h> |
49 | #include <linux/tracehook.h> | ||
49 | 50 | ||
50 | #include <asm/uaccess.h> | 51 | #include <asm/uaccess.h> |
51 | #include <asm/unistd.h> | 52 | #include <asm/unistd.h> |
@@ -120,18 +121,7 @@ static void __exit_signal(struct task_struct *tsk) | |||
120 | sig->nivcsw += tsk->nivcsw; | 121 | sig->nivcsw += tsk->nivcsw; |
121 | sig->inblock += task_io_get_inblock(tsk); | 122 | sig->inblock += task_io_get_inblock(tsk); |
122 | sig->oublock += task_io_get_oublock(tsk); | 123 | sig->oublock += task_io_get_oublock(tsk); |
123 | #ifdef CONFIG_TASK_XACCT | 124 | task_io_accounting_add(&sig->ioac, &tsk->ioac); |
124 | sig->rchar += tsk->rchar; | ||
125 | sig->wchar += tsk->wchar; | ||
126 | sig->syscr += tsk->syscr; | ||
127 | sig->syscw += tsk->syscw; | ||
128 | #endif /* CONFIG_TASK_XACCT */ | ||
129 | #ifdef CONFIG_TASK_IO_ACCOUNTING | ||
130 | sig->ioac.read_bytes += tsk->ioac.read_bytes; | ||
131 | sig->ioac.write_bytes += tsk->ioac.write_bytes; | ||
132 | sig->ioac.cancelled_write_bytes += | ||
133 | tsk->ioac.cancelled_write_bytes; | ||
134 | #endif /* CONFIG_TASK_IO_ACCOUNTING */ | ||
135 | sig->sum_sched_runtime += tsk->se.sum_exec_runtime; | 125 | sig->sum_sched_runtime += tsk->se.sum_exec_runtime; |
136 | sig = NULL; /* Marker for below. */ | 126 | sig = NULL; /* Marker for below. */ |
137 | } | 127 | } |
@@ -162,27 +152,17 @@ static void delayed_put_task_struct(struct rcu_head *rhp) | |||
162 | put_task_struct(container_of(rhp, struct task_struct, rcu)); | 152 | put_task_struct(container_of(rhp, struct task_struct, rcu)); |
163 | } | 153 | } |
164 | 154 | ||
165 | /* | ||
166 | * Do final ptrace-related cleanup of a zombie being reaped. | ||
167 | * | ||
168 | * Called with write_lock(&tasklist_lock) held. | ||
169 | */ | ||
170 | static void ptrace_release_task(struct task_struct *p) | ||
171 | { | ||
172 | BUG_ON(!list_empty(&p->ptraced)); | ||
173 | ptrace_unlink(p); | ||
174 | BUG_ON(!list_empty(&p->ptrace_entry)); | ||
175 | } | ||
176 | 155 | ||
177 | void release_task(struct task_struct * p) | 156 | void release_task(struct task_struct * p) |
178 | { | 157 | { |
179 | struct task_struct *leader; | 158 | struct task_struct *leader; |
180 | int zap_leader; | 159 | int zap_leader; |
181 | repeat: | 160 | repeat: |
161 | tracehook_prepare_release_task(p); | ||
182 | atomic_dec(&p->user->processes); | 162 | atomic_dec(&p->user->processes); |
183 | proc_flush_task(p); | 163 | proc_flush_task(p); |
184 | write_lock_irq(&tasklist_lock); | 164 | write_lock_irq(&tasklist_lock); |
185 | ptrace_release_task(p); | 165 | tracehook_finish_release_task(p); |
186 | __exit_signal(p); | 166 | __exit_signal(p); |
187 | 167 | ||
188 | /* | 168 | /* |
@@ -204,6 +184,13 @@ repeat: | |||
204 | * that case. | 184 | * that case. |
205 | */ | 185 | */ |
206 | zap_leader = task_detached(leader); | 186 | zap_leader = task_detached(leader); |
187 | |||
188 | /* | ||
189 | * This maintains the invariant that release_task() | ||
190 | * only runs on a task in EXIT_DEAD, just for sanity. | ||
191 | */ | ||
192 | if (zap_leader) | ||
193 | leader->exit_state = EXIT_DEAD; | ||
207 | } | 194 | } |
208 | 195 | ||
209 | write_unlock_irq(&tasklist_lock); | 196 | write_unlock_irq(&tasklist_lock); |
@@ -567,8 +554,6 @@ void put_fs_struct(struct fs_struct *fs) | |||
567 | if (atomic_dec_and_test(&fs->count)) { | 554 | if (atomic_dec_and_test(&fs->count)) { |
568 | path_put(&fs->root); | 555 | path_put(&fs->root); |
569 | path_put(&fs->pwd); | 556 | path_put(&fs->pwd); |
570 | if (fs->altroot.dentry) | ||
571 | path_put(&fs->altroot); | ||
572 | kmem_cache_free(fs_cachep, fs); | 557 | kmem_cache_free(fs_cachep, fs); |
573 | } | 558 | } |
574 | } | 559 | } |
@@ -887,7 +872,8 @@ static void forget_original_parent(struct task_struct *father) | |||
887 | */ | 872 | */ |
888 | static void exit_notify(struct task_struct *tsk, int group_dead) | 873 | static void exit_notify(struct task_struct *tsk, int group_dead) |
889 | { | 874 | { |
890 | int state; | 875 | int signal; |
876 | void *cookie; | ||
891 | 877 | ||
892 | /* | 878 | /* |
893 | * This does two things: | 879 | * This does two things: |
@@ -924,22 +910,11 @@ static void exit_notify(struct task_struct *tsk, int group_dead) | |||
924 | !capable(CAP_KILL)) | 910 | !capable(CAP_KILL)) |
925 | tsk->exit_signal = SIGCHLD; | 911 | tsk->exit_signal = SIGCHLD; |
926 | 912 | ||
927 | /* If something other than our normal parent is ptracing us, then | 913 | signal = tracehook_notify_death(tsk, &cookie, group_dead); |
928 | * send it a SIGCHLD instead of honoring exit_signal. exit_signal | 914 | if (signal > 0) |
929 | * only has special meaning to our real parent. | 915 | signal = do_notify_parent(tsk, signal); |
930 | */ | ||
931 | if (!task_detached(tsk) && thread_group_empty(tsk)) { | ||
932 | int signal = ptrace_reparented(tsk) ? | ||
933 | SIGCHLD : tsk->exit_signal; | ||
934 | do_notify_parent(tsk, signal); | ||
935 | } else if (tsk->ptrace) { | ||
936 | do_notify_parent(tsk, SIGCHLD); | ||
937 | } | ||
938 | 916 | ||
939 | state = EXIT_ZOMBIE; | 917 | tsk->exit_state = signal < 0 ? EXIT_DEAD : EXIT_ZOMBIE; |
940 | if (task_detached(tsk) && likely(!tsk->ptrace)) | ||
941 | state = EXIT_DEAD; | ||
942 | tsk->exit_state = state; | ||
943 | 918 | ||
944 | /* mt-exec, de_thread() is waiting for us */ | 919 | /* mt-exec, de_thread() is waiting for us */ |
945 | if (thread_group_leader(tsk) && | 920 | if (thread_group_leader(tsk) && |
@@ -949,8 +924,10 @@ static void exit_notify(struct task_struct *tsk, int group_dead) | |||
949 | 924 | ||
950 | write_unlock_irq(&tasklist_lock); | 925 | write_unlock_irq(&tasklist_lock); |
951 | 926 | ||
927 | tracehook_report_death(tsk, signal, cookie, group_dead); | ||
928 | |||
952 | /* If the process is dead, release it - nobody will wait for it */ | 929 | /* If the process is dead, release it - nobody will wait for it */ |
953 | if (state == EXIT_DEAD) | 930 | if (signal < 0) |
954 | release_task(tsk); | 931 | release_task(tsk); |
955 | } | 932 | } |
956 | 933 | ||
@@ -1029,10 +1006,7 @@ NORET_TYPE void do_exit(long code) | |||
1029 | if (unlikely(!tsk->pid)) | 1006 | if (unlikely(!tsk->pid)) |
1030 | panic("Attempted to kill the idle task!"); | 1007 | panic("Attempted to kill the idle task!"); |
1031 | 1008 | ||
1032 | if (unlikely(current->ptrace & PT_TRACE_EXIT)) { | 1009 | tracehook_report_exit(&code); |
1033 | current->ptrace_message = code; | ||
1034 | ptrace_notify((PTRACE_EVENT_EXIT << 8) | SIGTRAP); | ||
1035 | } | ||
1036 | 1010 | ||
1037 | /* | 1011 | /* |
1038 | * We're taking recursive faults here in do_exit. Safest is to just | 1012 | * We're taking recursive faults here in do_exit. Safest is to just |
@@ -1378,21 +1352,8 @@ static int wait_task_zombie(struct task_struct *p, int options, | |||
1378 | psig->coublock += | 1352 | psig->coublock += |
1379 | task_io_get_oublock(p) + | 1353 | task_io_get_oublock(p) + |
1380 | sig->oublock + sig->coublock; | 1354 | sig->oublock + sig->coublock; |
1381 | #ifdef CONFIG_TASK_XACCT | 1355 | task_io_accounting_add(&psig->ioac, &p->ioac); |
1382 | psig->rchar += p->rchar + sig->rchar; | 1356 | task_io_accounting_add(&psig->ioac, &sig->ioac); |
1383 | psig->wchar += p->wchar + sig->wchar; | ||
1384 | psig->syscr += p->syscr + sig->syscr; | ||
1385 | psig->syscw += p->syscw + sig->syscw; | ||
1386 | #endif /* CONFIG_TASK_XACCT */ | ||
1387 | #ifdef CONFIG_TASK_IO_ACCOUNTING | ||
1388 | psig->ioac.read_bytes += | ||
1389 | p->ioac.read_bytes + sig->ioac.read_bytes; | ||
1390 | psig->ioac.write_bytes += | ||
1391 | p->ioac.write_bytes + sig->ioac.write_bytes; | ||
1392 | psig->ioac.cancelled_write_bytes += | ||
1393 | p->ioac.cancelled_write_bytes + | ||
1394 | sig->ioac.cancelled_write_bytes; | ||
1395 | #endif /* CONFIG_TASK_IO_ACCOUNTING */ | ||
1396 | spin_unlock_irq(&p->parent->sighand->siglock); | 1357 | spin_unlock_irq(&p->parent->sighand->siglock); |
1397 | } | 1358 | } |
1398 | 1359 | ||