aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/exit.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/exit.c')
-rw-r--r--kernel/exit.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index 5b0fb9f09f21..6d2089a1bce7 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -368,17 +368,19 @@ 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 fdt = files_fdtable(files);
373 for (;;) { 375 for (;;) {
374 unsigned long set; 376 unsigned long set;
375 i = j * __NFDBITS; 377 i = j * __NFDBITS;
376 if (i >= files->max_fdset || i >= files->max_fds) 378 if (i >= fdt->max_fdset || i >= fdt->max_fds)
377 break; 379 break;
378 set = files->open_fds->fds_bits[j++]; 380 set = fdt->open_fds->fds_bits[j++];
379 while (set) { 381 while (set) {
380 if (set & 1) { 382 if (set & 1) {
381 struct file * file = xchg(&files->fd[i], NULL); 383 struct file * file = xchg(&fdt->fd[i], NULL);
382 if (file) 384 if (file)
383 filp_close(file, files); 385 filp_close(file, files);
384 } 386 }
@@ -403,18 +405,22 @@ struct files_struct *get_files_struct(struct task_struct *task)
403 405
404void fastcall put_files_struct(struct files_struct *files) 406void fastcall put_files_struct(struct files_struct *files)
405{ 407{
408 struct fdtable *fdt;
409
406 if (atomic_dec_and_test(&files->count)) { 410 if (atomic_dec_and_test(&files->count)) {
407 close_files(files); 411 close_files(files);
408 /* 412 /*
409 * Free the fd and fdset arrays if we expanded them. 413 * Free the fd and fdset arrays if we expanded them.
414 * If the fdtable was embedded, pass files for freeing
415 * at the end of the RCU grace period. Otherwise,
416 * you can free files immediately.
410 */ 417 */
411 if (files->fd != &files->fd_array[0]) 418 fdt = files_fdtable(files);
412 free_fd_array(files->fd, files->max_fds); 419 if (fdt == &files->fdtab)
413 if (files->max_fdset > __FD_SETSIZE) { 420 fdt->free_files = files;
414 free_fdset(files->open_fds, files->max_fdset); 421 else
415 free_fdset(files->close_on_exec, files->max_fdset); 422 kmem_cache_free(files_cachep, files);
416 } 423 free_fdtable(fdt);
417 kmem_cache_free(files_cachep, files);
418 } 424 }
419} 425}
420 426