diff options
-rw-r--r-- | fs/file.c | 27 | ||||
-rw-r--r-- | include/linux/file.h | 3 | ||||
-rw-r--r-- | include/linux/init_task.h | 1 | ||||
-rw-r--r-- | kernel/exit.c | 6 | ||||
-rw-r--r-- | kernel/fork.c | 1 |
5 files changed, 11 insertions, 27 deletions
@@ -91,7 +91,7 @@ static void free_fdtable_work(struct work_struct *work) | |||
91 | } | 91 | } |
92 | } | 92 | } |
93 | 93 | ||
94 | static void free_fdtable_rcu(struct rcu_head *rcu) | 94 | void free_fdtable_rcu(struct rcu_head *rcu) |
95 | { | 95 | { |
96 | struct fdtable *fdt = container_of(rcu, struct fdtable, rcu); | 96 | struct fdtable *fdt = container_of(rcu, struct fdtable, rcu); |
97 | int fdset_size, fdarray_size; | 97 | int fdset_size, fdarray_size; |
@@ -101,20 +101,15 @@ static void free_fdtable_rcu(struct rcu_head *rcu) | |||
101 | fdset_size = fdt->max_fds / 8; | 101 | fdset_size = fdt->max_fds / 8; |
102 | fdarray_size = fdt->max_fds * sizeof(struct file *); | 102 | fdarray_size = fdt->max_fds * sizeof(struct file *); |
103 | 103 | ||
104 | if (fdt->free_files) { | 104 | if (fdt->max_fds <= NR_OPEN_DEFAULT) { |
105 | /* | 105 | /* |
106 | * The this fdtable was embedded in the files structure | 106 | * This fdtable is embedded in the files structure and that |
107 | * and the files structure itself was getting destroyed. | 107 | * structure itself is getting destroyed. |
108 | * It is now safe to free the files structure. | ||
109 | */ | 108 | */ |
110 | kmem_cache_free(files_cachep, fdt->free_files); | 109 | kmem_cache_free(files_cachep, |
110 | container_of(fdt, struct files_struct, fdtab)); | ||
111 | return; | 111 | return; |
112 | } | 112 | } |
113 | if (fdt->max_fds <= NR_OPEN_DEFAULT) | ||
114 | /* | ||
115 | * The fdtable was embedded | ||
116 | */ | ||
117 | return; | ||
118 | if (fdset_size <= PAGE_SIZE && fdarray_size <= PAGE_SIZE) { | 113 | if (fdset_size <= PAGE_SIZE && fdarray_size <= PAGE_SIZE) { |
119 | kfree(fdt->open_fds); | 114 | kfree(fdt->open_fds); |
120 | kfree(fdt->close_on_exec); | 115 | kfree(fdt->close_on_exec); |
@@ -132,12 +127,6 @@ static void free_fdtable_rcu(struct rcu_head *rcu) | |||
132 | } | 127 | } |
133 | } | 128 | } |
134 | 129 | ||
135 | void free_fdtable(struct fdtable *fdt) | ||
136 | { | ||
137 | if (fdt->free_files || fdt->max_fds > NR_OPEN_DEFAULT) | ||
138 | call_rcu(&fdt->rcu, free_fdtable_rcu); | ||
139 | } | ||
140 | |||
141 | /* | 130 | /* |
142 | * Expand the fdset in the files_struct. Called with the files spinlock | 131 | * Expand the fdset in the files_struct. Called with the files spinlock |
143 | * held for write. | 132 | * held for write. |
@@ -247,7 +236,6 @@ static struct fdtable *alloc_fdtable(int nr) | |||
247 | goto out; | 236 | goto out; |
248 | fdt->fd = new_fds; | 237 | fdt->fd = new_fds; |
249 | fdt->max_fds = nfds; | 238 | fdt->max_fds = nfds; |
250 | fdt->free_files = NULL; | ||
251 | return fdt; | 239 | return fdt; |
252 | out: | 240 | out: |
253 | free_fdset(new_openset, nfds); | 241 | free_fdset(new_openset, nfds); |
@@ -283,7 +271,8 @@ static int expand_fdtable(struct files_struct *files, int nr) | |||
283 | /* Continue as planned */ | 271 | /* Continue as planned */ |
284 | copy_fdtable(new_fdt, cur_fdt); | 272 | copy_fdtable(new_fdt, cur_fdt); |
285 | rcu_assign_pointer(files->fdt, new_fdt); | 273 | rcu_assign_pointer(files->fdt, new_fdt); |
286 | free_fdtable(cur_fdt); | 274 | if (cur_fdt->max_fds > NR_OPEN_DEFAULT) |
275 | call_rcu(&cur_fdt->rcu, free_fdtable_rcu); | ||
287 | } else { | 276 | } else { |
288 | /* Somebody else expanded, so undo our attempt */ | 277 | /* Somebody else expanded, so undo our attempt */ |
289 | __free_fdtable(new_fdt); | 278 | __free_fdtable(new_fdt); |
diff --git a/include/linux/file.h b/include/linux/file.h index 02be4012225b..319118f275b0 100644 --- a/include/linux/file.h +++ b/include/linux/file.h | |||
@@ -32,7 +32,6 @@ struct fdtable { | |||
32 | fd_set *close_on_exec; | 32 | fd_set *close_on_exec; |
33 | fd_set *open_fds; | 33 | fd_set *open_fds; |
34 | struct rcu_head rcu; | 34 | struct rcu_head rcu; |
35 | struct files_struct *free_files; | ||
36 | struct fdtable *next; | 35 | struct fdtable *next; |
37 | }; | 36 | }; |
38 | 37 | ||
@@ -84,7 +83,7 @@ extern fd_set *alloc_fdset(int); | |||
84 | extern void free_fdset(fd_set *, int); | 83 | extern void free_fdset(fd_set *, int); |
85 | 84 | ||
86 | extern int expand_files(struct files_struct *, int nr); | 85 | extern int expand_files(struct files_struct *, int nr); |
87 | extern void free_fdtable(struct fdtable *fdt); | 86 | extern void free_fdtable_rcu(struct rcu_head *rcu); |
88 | extern void __init files_defer_init(void); | 87 | extern void __init files_defer_init(void); |
89 | 88 | ||
90 | static inline struct file * fcheck_files(struct files_struct *files, unsigned int fd) | 89 | static inline struct file * fcheck_files(struct files_struct *files, unsigned int fd) |
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 58c18daab65d..b5315150199e 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
@@ -16,7 +16,6 @@ | |||
16 | .close_on_exec = (fd_set *)&init_files.close_on_exec_init, \ | 16 | .close_on_exec = (fd_set *)&init_files.close_on_exec_init, \ |
17 | .open_fds = (fd_set *)&init_files.open_fds_init, \ | 17 | .open_fds = (fd_set *)&init_files.open_fds_init, \ |
18 | .rcu = RCU_HEAD_INIT, \ | 18 | .rcu = RCU_HEAD_INIT, \ |
19 | .free_files = NULL, \ | ||
20 | .next = NULL, \ | 19 | .next = NULL, \ |
21 | } | 20 | } |
22 | 21 | ||
diff --git a/kernel/exit.c b/kernel/exit.c index 5f77e76b4f97..122fadb972fc 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -466,11 +466,9 @@ void fastcall put_files_struct(struct files_struct *files) | |||
466 | * you can free files immediately. | 466 | * you can free files immediately. |
467 | */ | 467 | */ |
468 | fdt = files_fdtable(files); | 468 | fdt = files_fdtable(files); |
469 | if (fdt == &files->fdtab) | 469 | if (fdt != &files->fdtab) |
470 | fdt->free_files = files; | ||
471 | else | ||
472 | kmem_cache_free(files_cachep, files); | 470 | kmem_cache_free(files_cachep, files); |
473 | free_fdtable(fdt); | 471 | call_rcu(&fdt->rcu, free_fdtable_rcu); |
474 | } | 472 | } |
475 | } | 473 | } |
476 | 474 | ||
diff --git a/kernel/fork.c b/kernel/fork.c index aba595424f78..d16c566eb645 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -645,7 +645,6 @@ static struct files_struct *alloc_files(void) | |||
645 | fdt->open_fds = (fd_set *)&newf->open_fds_init; | 645 | fdt->open_fds = (fd_set *)&newf->open_fds_init; |
646 | fdt->fd = &newf->fd_array[0]; | 646 | fdt->fd = &newf->fd_array[0]; |
647 | INIT_RCU_HEAD(&fdt->rcu); | 647 | INIT_RCU_HEAD(&fdt->rcu); |
648 | fdt->free_files = NULL; | ||
649 | fdt->next = NULL; | 648 | fdt->next = NULL; |
650 | rcu_assign_pointer(newf->fdt, fdt); | 649 | rcu_assign_pointer(newf->fdt, fdt); |
651 | out: | 650 | out: |