aboutsummaryrefslogtreecommitdiffstats
path: root/fs/file.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2013-04-28 21:42:33 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2013-05-01 17:31:42 -0400
commitac3e3c5b1164397656df81b9e9ab4991184d3236 (patch)
tree3f2f0db03d858eff7a97cc71779cd844a8387391 /fs/file.c
parent094dd33b178d52c9ef959ed62cc0759310bd9657 (diff)
don't bother with deferred freeing of fdtables
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/file.c')
-rw-r--r--fs/file.c68
1 files changed, 2 insertions, 66 deletions
diff --git a/fs/file.c b/fs/file.c
index 3906d9577a18..4a78f981557a 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -23,24 +23,10 @@
23#include <linux/rcupdate.h> 23#include <linux/rcupdate.h>
24#include <linux/workqueue.h> 24#include <linux/workqueue.h>
25 25
26struct fdtable_defer {
27 spinlock_t lock;
28 struct work_struct wq;
29 struct fdtable *next;
30};
31
32int sysctl_nr_open __read_mostly = 1024*1024; 26int sysctl_nr_open __read_mostly = 1024*1024;
33int sysctl_nr_open_min = BITS_PER_LONG; 27int sysctl_nr_open_min = BITS_PER_LONG;
34int sysctl_nr_open_max = 1024 * 1024; /* raised later */ 28int sysctl_nr_open_max = 1024 * 1024; /* raised later */
35 29
36/*
37 * We use this list to defer free fdtables that have vmalloced
38 * sets/arrays. By keeping a per-cpu list, we avoid having to embed
39 * the work_struct in fdtable itself which avoids a 64 byte (i386) increase in
40 * this per-task structure.
41 */
42static DEFINE_PER_CPU(struct fdtable_defer, fdtable_defer_list);
43
44static void *alloc_fdmem(size_t size) 30static void *alloc_fdmem(size_t size)
45{ 31{
46 /* 32 /*
@@ -67,46 +53,9 @@ static void __free_fdtable(struct fdtable *fdt)
67 kfree(fdt); 53 kfree(fdt);
68} 54}
69 55
70static void free_fdtable_work(struct work_struct *work)
71{
72 struct fdtable_defer *f =
73 container_of(work, struct fdtable_defer, wq);
74 struct fdtable *fdt;
75
76 spin_lock_bh(&f->lock);
77 fdt = f->next;
78 f->next = NULL;
79 spin_unlock_bh(&f->lock);
80 while(fdt) {
81 struct fdtable *next = fdt->next;
82
83 __free_fdtable(fdt);
84 fdt = next;
85 }
86}
87
88static void free_fdtable_rcu(struct rcu_head *rcu) 56static void free_fdtable_rcu(struct rcu_head *rcu)
89{ 57{
90 struct fdtable *fdt = container_of(rcu, struct fdtable, rcu); 58 __free_fdtable(container_of(rcu, struct fdtable, rcu));
91 struct fdtable_defer *fddef;
92
93 BUG_ON(!fdt);
94 BUG_ON(fdt->max_fds <= NR_OPEN_DEFAULT);
95
96 if (!is_vmalloc_addr(fdt->fd) && !is_vmalloc_addr(fdt->open_fds)) {
97 kfree(fdt->fd);
98 kfree(fdt->open_fds);
99 kfree(fdt);
100 } else {
101 fddef = &get_cpu_var(fdtable_defer_list);
102 spin_lock(&fddef->lock);
103 fdt->next = fddef->next;
104 fddef->next = fdt;
105 /* vmallocs are handled from the workqueue context */
106 schedule_work(&fddef->wq);
107 spin_unlock(&fddef->lock);
108 put_cpu_var(fdtable_defer_list);
109 }
110} 59}
111 60
112/* 61/*
@@ -174,7 +123,6 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
174 fdt->open_fds = data; 123 fdt->open_fds = data;
175 data += nr / BITS_PER_BYTE; 124 data += nr / BITS_PER_BYTE;
176 fdt->close_on_exec = data; 125 fdt->close_on_exec = data;
177 fdt->next = NULL;
178 126
179 return fdt; 127 return fdt;
180 128
@@ -221,7 +169,7 @@ static int expand_fdtable(struct files_struct *files, int nr)
221 /* Continue as planned */ 169 /* Continue as planned */
222 copy_fdtable(new_fdt, cur_fdt); 170 copy_fdtable(new_fdt, cur_fdt);
223 rcu_assign_pointer(files->fdt, new_fdt); 171 rcu_assign_pointer(files->fdt, new_fdt);
224 if (cur_fdt->max_fds > NR_OPEN_DEFAULT) 172 if (cur_fdt != &files->fdtab)
225 call_rcu(&cur_fdt->rcu, free_fdtable_rcu); 173 call_rcu(&cur_fdt->rcu, free_fdtable_rcu);
226 } else { 174 } else {
227 /* Somebody else expanded, so undo our attempt */ 175 /* Somebody else expanded, so undo our attempt */
@@ -316,7 +264,6 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
316 new_fdt->close_on_exec = newf->close_on_exec_init; 264 new_fdt->close_on_exec = newf->close_on_exec_init;
317 new_fdt->open_fds = newf->open_fds_init; 265 new_fdt->open_fds = newf->open_fds_init;
318 new_fdt->fd = &newf->fd_array[0]; 266 new_fdt->fd = &newf->fd_array[0];
319 new_fdt->next = NULL;
320 267
321 spin_lock(&oldf->file_lock); 268 spin_lock(&oldf->file_lock);
322 old_fdt = files_fdtable(oldf); 269 old_fdt = files_fdtable(oldf);
@@ -490,19 +437,8 @@ void exit_files(struct task_struct *tsk)
490 } 437 }
491} 438}
492 439
493static void fdtable_defer_list_init(int cpu)
494{
495 struct fdtable_defer *fddef = &per_cpu(fdtable_defer_list, cpu);
496 spin_lock_init(&fddef->lock);
497 INIT_WORK(&fddef->wq, free_fdtable_work);
498 fddef->next = NULL;
499}
500
501void __init files_defer_init(void) 440void __init files_defer_init(void)
502{ 441{
503 int i;
504 for_each_possible_cpu(i)
505 fdtable_defer_list_init(i);
506 sysctl_nr_open_max = min((size_t)INT_MAX, ~(size_t)0/sizeof(void *)) & 442 sysctl_nr_open_max = min((size_t)INT_MAX, ~(size_t)0/sizeof(void *)) &
507 -BITS_PER_LONG; 443 -BITS_PER_LONG;
508} 444}