diff options
author | Dipankar Sarma <dipankar@in.ibm.com> | 2005-09-09 16:04:10 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-09 16:57:55 -0400 |
commit | badf16621c1f9d1ac753be056fce11b43d6e0be5 (patch) | |
tree | 3fdf833fdf2e3d3a439090743539680449ec3428 /kernel/exit.c | |
parent | c0dfb2905126e9e94edebbce8d3e05001301f52d (diff) |
[PATCH] files: break up files struct
In order for the RCU to work, the file table array, sets and their sizes must
be updated atomically. Instead of ensuring this through too many memory
barriers, we put the arrays and their sizes in a separate structure. This
patch takes the first step of putting the file table elements in a separate
structure fdtable that is embedded withing files_struct. It also changes all
the users to refer to the file table using files_fdtable() macro. Subsequent
applciation of RCU becomes easier after this.
Signed-off-by: Dipankar Sarma <dipankar@in.ibm.com>
Signed-Off-By: David Howells <dhowells@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel/exit.c')
-rw-r--r-- | kernel/exit.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index 5b0fb9f09f21..83beb1e93b18 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -368,17 +368,19 @@ EXPORT_SYMBOL(daemonize); | |||
368 | static inline void close_files(struct files_struct * files) | 368 | static 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,16 +405,19 @@ struct files_struct *get_files_struct(struct task_struct *task) | |||
403 | 405 | ||
404 | void fastcall put_files_struct(struct files_struct *files) | 406 | void 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. |
410 | */ | 414 | */ |
411 | if (files->fd != &files->fd_array[0]) | 415 | fdt = files_fdtable(files); |
412 | free_fd_array(files->fd, files->max_fds); | 416 | if (fdt->fd != &files->fd_array[0]) |
413 | if (files->max_fdset > __FD_SETSIZE) { | 417 | free_fd_array(fdt->fd, fdt->max_fds); |
414 | free_fdset(files->open_fds, files->max_fdset); | 418 | if (fdt->max_fdset > __FD_SETSIZE) { |
415 | free_fdset(files->close_on_exec, files->max_fdset); | 419 | free_fdset(fdt->open_fds, fdt->max_fdset); |
420 | free_fdset(fdt->close_on_exec, fdt->max_fdset); | ||
416 | } | 421 | } |
417 | kmem_cache_free(files_cachep, files); | 422 | kmem_cache_free(files_cachep, files); |
418 | } | 423 | } |