diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/compat.c | 10 | ||||
-rw-r--r-- | fs/exec.c | 2 | ||||
-rw-r--r-- | fs/fcntl.c | 5 | ||||
-rw-r--r-- | fs/file.c | 56 | ||||
-rw-r--r-- | fs/open.c | 3 | ||||
-rw-r--r-- | fs/select.c | 10 |
6 files changed, 36 insertions, 50 deletions
diff --git a/fs/compat.c b/fs/compat.c index b766964a625c..0ec70e3cee0a 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -1679,19 +1679,19 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp, | |||
1679 | { | 1679 | { |
1680 | fd_set_bits fds; | 1680 | fd_set_bits fds; |
1681 | char *bits; | 1681 | char *bits; |
1682 | int size, max_fdset, ret = -EINVAL; | 1682 | int size, max_fds, ret = -EINVAL; |
1683 | struct fdtable *fdt; | 1683 | struct fdtable *fdt; |
1684 | 1684 | ||
1685 | if (n < 0) | 1685 | if (n < 0) |
1686 | goto out_nofds; | 1686 | goto out_nofds; |
1687 | 1687 | ||
1688 | /* max_fdset can increase, so grab it once to avoid race */ | 1688 | /* max_fds can increase, so grab it once to avoid race */ |
1689 | rcu_read_lock(); | 1689 | rcu_read_lock(); |
1690 | fdt = files_fdtable(current->files); | 1690 | fdt = files_fdtable(current->files); |
1691 | max_fdset = fdt->max_fdset; | 1691 | max_fds = fdt->max_fds; |
1692 | rcu_read_unlock(); | 1692 | rcu_read_unlock(); |
1693 | if (n > max_fdset) | 1693 | if (n > max_fds) |
1694 | n = max_fdset; | 1694 | n = max_fds; |
1695 | 1695 | ||
1696 | /* | 1696 | /* |
1697 | * We need 6 bitmaps (in/out/ex for both incoming and outgoing), | 1697 | * We need 6 bitmaps (in/out/ex for both incoming and outgoing), |
@@ -783,7 +783,7 @@ static void flush_old_files(struct files_struct * files) | |||
783 | j++; | 783 | j++; |
784 | i = j * __NFDBITS; | 784 | i = j * __NFDBITS; |
785 | fdt = files_fdtable(files); | 785 | fdt = files_fdtable(files); |
786 | if (i >= fdt->max_fds || i >= fdt->max_fdset) | 786 | if (i >= fdt->max_fds) |
787 | break; | 787 | break; |
788 | set = fdt->close_on_exec->fds_bits[j]; | 788 | set = fdt->close_on_exec->fds_bits[j]; |
789 | if (!set) | 789 | if (!set) |
diff --git a/fs/fcntl.c b/fs/fcntl.c index 2bdaef35da54..8e382a5d51bd 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
@@ -77,10 +77,9 @@ repeat: | |||
77 | start = files->next_fd; | 77 | start = files->next_fd; |
78 | 78 | ||
79 | newfd = start; | 79 | newfd = start; |
80 | if (start < fdt->max_fdset) { | 80 | if (start < fdt->max_fds) |
81 | newfd = find_next_zero_bit(fdt->open_fds->fds_bits, | 81 | newfd = find_next_zero_bit(fdt->open_fds->fds_bits, |
82 | fdt->max_fdset, start); | 82 | fdt->max_fds, start); |
83 | } | ||
84 | 83 | ||
85 | error = -EMFILE; | 84 | error = -EMFILE; |
86 | if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) | 85 | if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) |
@@ -68,8 +68,8 @@ void free_fd_array(struct file **array, int num) | |||
68 | 68 | ||
69 | static void __free_fdtable(struct fdtable *fdt) | 69 | static void __free_fdtable(struct fdtable *fdt) |
70 | { | 70 | { |
71 | free_fdset(fdt->open_fds, fdt->max_fdset); | 71 | free_fdset(fdt->open_fds, fdt->max_fds); |
72 | free_fdset(fdt->close_on_exec, fdt->max_fdset); | 72 | free_fdset(fdt->close_on_exec, fdt->max_fds); |
73 | free_fd_array(fdt->fd, fdt->max_fds); | 73 | free_fd_array(fdt->fd, fdt->max_fds); |
74 | kfree(fdt); | 74 | kfree(fdt); |
75 | } | 75 | } |
@@ -98,7 +98,7 @@ static void free_fdtable_rcu(struct rcu_head *rcu) | |||
98 | struct fdtable_defer *fddef; | 98 | struct fdtable_defer *fddef; |
99 | 99 | ||
100 | BUG_ON(!fdt); | 100 | BUG_ON(!fdt); |
101 | fdset_size = fdt->max_fdset / 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->free_files) { |
@@ -110,13 +110,11 @@ static void free_fdtable_rcu(struct rcu_head *rcu) | |||
110 | kmem_cache_free(files_cachep, fdt->free_files); | 110 | kmem_cache_free(files_cachep, fdt->free_files); |
111 | return; | 111 | return; |
112 | } | 112 | } |
113 | if (fdt->max_fdset <= EMBEDDED_FD_SET_SIZE && | 113 | if (fdt->max_fds <= NR_OPEN_DEFAULT) |
114 | fdt->max_fds <= NR_OPEN_DEFAULT) { | ||
115 | /* | 114 | /* |
116 | * The fdtable was embedded | 115 | * The fdtable was embedded |
117 | */ | 116 | */ |
118 | return; | 117 | return; |
119 | } | ||
120 | if (fdset_size <= PAGE_SIZE && fdarray_size <= PAGE_SIZE) { | 118 | if (fdset_size <= PAGE_SIZE && fdarray_size <= PAGE_SIZE) { |
121 | kfree(fdt->open_fds); | 119 | kfree(fdt->open_fds); |
122 | kfree(fdt->close_on_exec); | 120 | kfree(fdt->close_on_exec); |
@@ -136,9 +134,7 @@ static void free_fdtable_rcu(struct rcu_head *rcu) | |||
136 | 134 | ||
137 | void free_fdtable(struct fdtable *fdt) | 135 | void free_fdtable(struct fdtable *fdt) |
138 | { | 136 | { |
139 | if (fdt->free_files || | 137 | if (fdt->free_files || fdt->max_fds > NR_OPEN_DEFAULT) |
140 | fdt->max_fdset > EMBEDDED_FD_SET_SIZE || | ||
141 | fdt->max_fds > NR_OPEN_DEFAULT) | ||
142 | call_rcu(&fdt->rcu, free_fdtable_rcu); | 138 | call_rcu(&fdt->rcu, free_fdtable_rcu); |
143 | } | 139 | } |
144 | 140 | ||
@@ -151,12 +147,11 @@ static void copy_fdtable(struct fdtable *nfdt, struct fdtable *fdt) | |||
151 | int i; | 147 | int i; |
152 | int count; | 148 | int count; |
153 | 149 | ||
154 | BUG_ON(nfdt->max_fdset < fdt->max_fdset); | ||
155 | BUG_ON(nfdt->max_fds < fdt->max_fds); | 150 | BUG_ON(nfdt->max_fds < fdt->max_fds); |
156 | /* Copy the existing tables and install the new pointers */ | 151 | /* Copy the existing tables and install the new pointers */ |
157 | 152 | ||
158 | i = fdt->max_fdset / (sizeof(unsigned long) * 8); | 153 | i = fdt->max_fds / (sizeof(unsigned long) * 8); |
159 | count = (nfdt->max_fdset - fdt->max_fdset) / 8; | 154 | count = (nfdt->max_fds - fdt->max_fds) / 8; |
160 | 155 | ||
161 | /* | 156 | /* |
162 | * Don't copy the entire array if the current fdset is | 157 | * Don't copy the entire array if the current fdset is |
@@ -164,9 +159,9 @@ static void copy_fdtable(struct fdtable *nfdt, struct fdtable *fdt) | |||
164 | */ | 159 | */ |
165 | if (i) { | 160 | if (i) { |
166 | memcpy (nfdt->open_fds, fdt->open_fds, | 161 | memcpy (nfdt->open_fds, fdt->open_fds, |
167 | fdt->max_fdset/8); | 162 | fdt->max_fds/8); |
168 | memcpy (nfdt->close_on_exec, fdt->close_on_exec, | 163 | memcpy (nfdt->close_on_exec, fdt->close_on_exec, |
169 | fdt->max_fdset/8); | 164 | fdt->max_fds/8); |
170 | memset (&nfdt->open_fds->fds_bits[i], 0, count); | 165 | memset (&nfdt->open_fds->fds_bits[i], 0, count); |
171 | memset (&nfdt->close_on_exec->fds_bits[i], 0, count); | 166 | memset (&nfdt->close_on_exec->fds_bits[i], 0, count); |
172 | } | 167 | } |
@@ -201,7 +196,7 @@ fd_set * alloc_fdset(int num) | |||
201 | 196 | ||
202 | void free_fdset(fd_set *array, int num) | 197 | void free_fdset(fd_set *array, int num) |
203 | { | 198 | { |
204 | if (num <= EMBEDDED_FD_SET_SIZE) /* Don't free an embedded fdset */ | 199 | if (num <= NR_OPEN_DEFAULT) /* Don't free an embedded fdset */ |
205 | return; | 200 | return; |
206 | else if (num <= 8 * PAGE_SIZE) | 201 | else if (num <= 8 * PAGE_SIZE) |
207 | kfree(array); | 202 | kfree(array); |
@@ -220,18 +215,6 @@ static struct fdtable *alloc_fdtable(int nr) | |||
220 | if (!fdt) | 215 | if (!fdt) |
221 | goto out; | 216 | goto out; |
222 | 217 | ||
223 | nfds = max_t(int, 8 * L1_CACHE_BYTES, roundup_pow_of_two(nr + 1)); | ||
224 | if (nfds > NR_OPEN) | ||
225 | nfds = NR_OPEN; | ||
226 | |||
227 | new_openset = alloc_fdset(nfds); | ||
228 | new_execset = alloc_fdset(nfds); | ||
229 | if (!new_openset || !new_execset) | ||
230 | goto out; | ||
231 | fdt->open_fds = new_openset; | ||
232 | fdt->close_on_exec = new_execset; | ||
233 | fdt->max_fdset = nfds; | ||
234 | |||
235 | nfds = NR_OPEN_DEFAULT; | 218 | nfds = NR_OPEN_DEFAULT; |
236 | /* | 219 | /* |
237 | * Expand to the max in easy steps, and keep expanding it until | 220 | * Expand to the max in easy steps, and keep expanding it until |
@@ -251,15 +234,21 @@ static struct fdtable *alloc_fdtable(int nr) | |||
251 | nfds = NR_OPEN; | 234 | nfds = NR_OPEN; |
252 | } | 235 | } |
253 | } while (nfds <= nr); | 236 | } while (nfds <= nr); |
237 | |||
238 | new_openset = alloc_fdset(nfds); | ||
239 | new_execset = alloc_fdset(nfds); | ||
240 | if (!new_openset || !new_execset) | ||
241 | goto out; | ||
242 | fdt->open_fds = new_openset; | ||
243 | fdt->close_on_exec = new_execset; | ||
244 | |||
254 | new_fds = alloc_fd_array(nfds); | 245 | new_fds = alloc_fd_array(nfds); |
255 | if (!new_fds) | 246 | if (!new_fds) |
256 | goto out2; | 247 | goto out; |
257 | fdt->fd = new_fds; | 248 | fdt->fd = new_fds; |
258 | fdt->max_fds = nfds; | 249 | fdt->max_fds = nfds; |
259 | fdt->free_files = NULL; | 250 | fdt->free_files = NULL; |
260 | return fdt; | 251 | return fdt; |
261 | out2: | ||
262 | nfds = fdt->max_fdset; | ||
263 | out: | 252 | out: |
264 | free_fdset(new_openset, nfds); | 253 | free_fdset(new_openset, nfds); |
265 | free_fdset(new_execset, nfds); | 254 | free_fdset(new_execset, nfds); |
@@ -290,7 +279,7 @@ static int expand_fdtable(struct files_struct *files, int nr) | |||
290 | * we dropped the lock | 279 | * we dropped the lock |
291 | */ | 280 | */ |
292 | cur_fdt = files_fdtable(files); | 281 | cur_fdt = files_fdtable(files); |
293 | if (nr >= cur_fdt->max_fds || nr >= cur_fdt->max_fdset) { | 282 | if (nr >= cur_fdt->max_fds) { |
294 | /* Continue as planned */ | 283 | /* Continue as planned */ |
295 | copy_fdtable(new_fdt, cur_fdt); | 284 | copy_fdtable(new_fdt, cur_fdt); |
296 | rcu_assign_pointer(files->fdt, new_fdt); | 285 | rcu_assign_pointer(files->fdt, new_fdt); |
@@ -316,11 +305,10 @@ int expand_files(struct files_struct *files, int nr) | |||
316 | 305 | ||
317 | fdt = files_fdtable(files); | 306 | fdt = files_fdtable(files); |
318 | /* Do we need to expand? */ | 307 | /* Do we need to expand? */ |
319 | if (nr < fdt->max_fdset && nr < fdt->max_fds) | 308 | if (nr < fdt->max_fds) |
320 | return 0; | 309 | return 0; |
321 | /* Can we expand? */ | 310 | /* Can we expand? */ |
322 | if (fdt->max_fdset >= NR_OPEN || fdt->max_fds >= NR_OPEN || | 311 | if (nr >= NR_OPEN) |
323 | nr >= NR_OPEN) | ||
324 | return -EMFILE; | 312 | return -EMFILE; |
325 | 313 | ||
326 | /* All good, so we try */ | 314 | /* All good, so we try */ |
@@ -864,8 +864,7 @@ int get_unused_fd(void) | |||
864 | 864 | ||
865 | repeat: | 865 | repeat: |
866 | fdt = files_fdtable(files); | 866 | fdt = files_fdtable(files); |
867 | fd = find_next_zero_bit(fdt->open_fds->fds_bits, | 867 | fd = find_next_zero_bit(fdt->open_fds->fds_bits, fdt->max_fds, |
868 | fdt->max_fdset, | ||
869 | files->next_fd); | 868 | files->next_fd); |
870 | 869 | ||
871 | /* | 870 | /* |
diff --git a/fs/select.c b/fs/select.c index dcbc1112b7ec..fe0893afd931 100644 --- a/fs/select.c +++ b/fs/select.c | |||
@@ -311,7 +311,7 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp, | |||
311 | { | 311 | { |
312 | fd_set_bits fds; | 312 | fd_set_bits fds; |
313 | void *bits; | 313 | void *bits; |
314 | int ret, max_fdset; | 314 | int ret, max_fds; |
315 | unsigned int size; | 315 | unsigned int size; |
316 | struct fdtable *fdt; | 316 | struct fdtable *fdt; |
317 | /* Allocate small arguments on the stack to save memory and be faster */ | 317 | /* Allocate small arguments on the stack to save memory and be faster */ |
@@ -321,13 +321,13 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp, | |||
321 | if (n < 0) | 321 | if (n < 0) |
322 | goto out_nofds; | 322 | goto out_nofds; |
323 | 323 | ||
324 | /* max_fdset can increase, so grab it once to avoid race */ | 324 | /* max_fds can increase, so grab it once to avoid race */ |
325 | rcu_read_lock(); | 325 | rcu_read_lock(); |
326 | fdt = files_fdtable(current->files); | 326 | fdt = files_fdtable(current->files); |
327 | max_fdset = fdt->max_fdset; | 327 | max_fds = fdt->max_fds; |
328 | rcu_read_unlock(); | 328 | rcu_read_unlock(); |
329 | if (n > max_fdset) | 329 | if (n > max_fds) |
330 | n = max_fdset; | 330 | n = max_fds; |
331 | 331 | ||
332 | /* | 332 | /* |
333 | * We need 6 bitmaps (in/out/ex for both incoming and outgoing), | 333 | * We need 6 bitmaps (in/out/ex for both incoming and outgoing), |