diff options
Diffstat (limited to 'fs/file.c')
-rw-r--r-- | fs/file.c | 27 |
1 files changed, 8 insertions, 19 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); |