]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - kernel/exit.c
Merge branch 'elevator-switch' of git://brick.kernel.dk/data/git/linux-2.6-block
[karo-tx-linux.git] / kernel / exit.c
index 83beb1e93b18c77d3f2fb1d2cfb21e3f9e66c28e..3b25b182d2be35cfe8ddc69c53a908da96ce5aec 100644 (file)
@@ -371,6 +371,12 @@ static inline void close_files(struct files_struct * files)
        struct fdtable *fdt;
 
        j = 0;
+
+       /*
+        * It is safe to dereference the fd table without RCU or
+        * ->file_lock because this is the last reference to the
+        * files structure.
+        */
        fdt = files_fdtable(files);
        for (;;) {
                unsigned long set;
@@ -411,15 +417,16 @@ void fastcall put_files_struct(struct files_struct *files)
                close_files(files);
                /*
                 * Free the fd and fdset arrays if we expanded them.
+                * If the fdtable was embedded, pass files for freeing
+                * at the end of the RCU grace period. Otherwise,
+                * you can free files immediately.
                 */
                fdt = files_fdtable(files);
-               if (fdt->fd != &files->fd_array[0])
-                       free_fd_array(fdt->fd, fdt->max_fds);
-               if (fdt->max_fdset > __FD_SETSIZE) {
-                       free_fdset(fdt->open_fds, fdt->max_fdset);
-                       free_fdset(fdt->close_on_exec, fdt->max_fdset);
-               }
-               kmem_cache_free(files_cachep, files);
+               if (fdt == &files->fdtab)
+                       fdt->free_files = files;
+               else
+                       kmem_cache_free(files_cachep, files);
+               free_fdtable(fdt);
        }
 }
 
@@ -836,6 +843,7 @@ fastcall NORET_TYPE void do_exit(long code)
        group_dead = atomic_dec_and_test(&tsk->signal->live);
        if (group_dead) {
                del_timer_sync(&tsk->signal->real_timer);
+               exit_itimers(tsk->signal);
                acct_process(code);
        }
        exit_mm(tsk);
@@ -1196,7 +1204,7 @@ static int wait_task_stopped(task_t *p, int delayed_group_leader, int noreap,
 
                exit_code = p->exit_code;
                if (unlikely(!exit_code) ||
-                   unlikely(p->state > TASK_STOPPED))
+                   unlikely(p->state & TASK_TRACED))
                        goto bail_ref;
                return wait_noreap_copyout(p, pid, uid,
                                           why, (exit_code << 8) | 0x7f,