diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-04-28 21:42:33 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-05-01 17:31:42 -0400 |
commit | ac3e3c5b1164397656df81b9e9ab4991184d3236 (patch) | |
tree | 3f2f0db03d858eff7a97cc71779cd844a8387391 /fs/file.c | |
parent | 094dd33b178d52c9ef959ed62cc0759310bd9657 (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.c | 68 |
1 files changed, 2 insertions, 66 deletions
@@ -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 | ||
26 | struct fdtable_defer { | ||
27 | spinlock_t lock; | ||
28 | struct work_struct wq; | ||
29 | struct fdtable *next; | ||
30 | }; | ||
31 | |||
32 | int sysctl_nr_open __read_mostly = 1024*1024; | 26 | int sysctl_nr_open __read_mostly = 1024*1024; |
33 | int sysctl_nr_open_min = BITS_PER_LONG; | 27 | int sysctl_nr_open_min = BITS_PER_LONG; |
34 | int sysctl_nr_open_max = 1024 * 1024; /* raised later */ | 28 | int 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 | */ | ||
42 | static DEFINE_PER_CPU(struct fdtable_defer, fdtable_defer_list); | ||
43 | |||
44 | static void *alloc_fdmem(size_t size) | 30 | static 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 | ||
70 | static 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 | |||
88 | static void free_fdtable_rcu(struct rcu_head *rcu) | 56 | static 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 | ||
493 | static 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 | |||
501 | void __init files_defer_init(void) | 440 | void __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 | } |