aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/exit.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/exit.c')
-rw-r--r--kernel/exit.c35
1 files changed, 24 insertions, 11 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index 5b0fb9f09f21..3b25b182d2be 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -368,17 +368,25 @@ EXPORT_SYMBOL(daemonize);
368static inline void close_files(struct files_struct * files) 368static inline void close_files(struct files_struct * files)
369{ 369{
370 int i, j; 370 int i, j;
371 struct fdtable *fdt;
371 372
372 j = 0; 373 j = 0;
374
375 /*
376 * It is safe to dereference the fd table without RCU or
377 * ->file_lock because this is the last reference to the
378 * files structure.
379 */
380 fdt = files_fdtable(files);
373 for (;;) { 381 for (;;) {
374 unsigned long set; 382 unsigned long set;
375 i = j * __NFDBITS; 383 i = j * __NFDBITS;
376 if (i >= files->max_fdset || i >= files->max_fds) 384 if (i >= fdt->max_fdset || i >= fdt->max_fds)
377 break; 385 break;
378 set = files->open_fds->fds_bits[j++]; 386 set = fdt->open_fds->fds_bits[j++];
379 while (set) { 387 while (set) {
380 if (set & 1) { 388 if (set & 1) {
381 struct file * file = xchg(&files->fd[i], NULL); 389 struct file * file = xchg(&fdt->fd[i], NULL);
382 if (file) 390 if (file)
383 filp_close(file, files); 391 filp_close(file, files);
384 } 392 }
@@ -403,18 +411,22 @@ struct files_struct *get_files_struct(struct task_struct *task)
403 411
404void fastcall put_files_struct(struct files_struct *files) 412void fastcall put_files_struct(struct files_struct *files)
405{ 413{
414 struct fdtable *fdt;
415
406 if (atomic_dec_and_test(&files->count)) { 416 if (atomic_dec_and_test(&files->count)) {
407 close_files(files); 417 close_files(files);
408 /* 418 /*
409 * Free the fd and fdset arrays if we expanded them. 419 * Free the fd and fdset arrays if we expanded them.
420 * If the fdtable was embedded, pass files for freeing
421 * at the end of the RCU grace period. Otherwise,
422 * you can free files immediately.
410 */ 423 */
411 if (files->fd != &files->fd_array[0]) 424 fdt = files_fdtable(files);
412 free_fd_array(files->fd, files->max_fds); 425 if (fdt == &files->fdtab)
413 if (files->max_fdset > __FD_SETSIZE) { 426 fdt->free_files = files;
414 free_fdset(files->open_fds, files->max_fdset); 427 else
415 free_fdset(files->close_on_exec, files->max_fdset); 428 kmem_cache_free(files_cachep, files);
416 } 429 free_fdtable(fdt);
417 kmem_cache_free(files_cachep, files);
418 } 430 }
419} 431}
420 432
@@ -831,6 +843,7 @@ fastcall NORET_TYPE void do_exit(long code)
831 group_dead = atomic_dec_and_test(&tsk->signal->live); 843 group_dead = atomic_dec_and_test(&tsk->signal->live);
832 if (group_dead) { 844 if (group_dead) {
833 del_timer_sync(&tsk->signal->real_timer); 845 del_timer_sync(&tsk->signal->real_timer);
846 exit_itimers(tsk->signal);
834 acct_process(code); 847 acct_process(code);
835 } 848 }
836 exit_mm(tsk); 849 exit_mm(tsk);
@@ -1191,7 +1204,7 @@ static int wait_task_stopped(task_t *p, int delayed_group_leader, int noreap,
1191 1204
1192 exit_code = p->exit_code; 1205 exit_code = p->exit_code;
1193 if (unlikely(!exit_code) || 1206 if (unlikely(!exit_code) ||
1194 unlikely(p->state > TASK_STOPPED)) 1207 unlikely(p->state & TASK_TRACED))
1195 goto bail_ref; 1208 goto bail_ref;
1196 return wait_noreap_copyout(p, pid, uid, 1209 return wait_noreap_copyout(p, pid, uid,
1197 why, (exit_code << 8) | 0x7f, 1210 why, (exit_code << 8) | 0x7f,