aboutsummaryrefslogtreecommitdiffstats
path: root/fs/file.c
diff options
context:
space:
mode:
authorVadim Lobanov <vlobanov@speakeasy.net>2006-12-10 05:21:12 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-10 12:57:22 -0500
commitbbea9f69668a3d0cf9feba15a724cd02896f8675 (patch)
treebc58506e4daba4a04309181a5501ae4eb5424783 /fs/file.c
parentf3d19c90fb117a5f080310a4592929aa8e1ad8e9 (diff)
[PATCH] fdtable: Make fdarray and fdsets equal in size
Currently, each fdtable supports three dynamically-sized arrays of data: the fdarray and two fdsets. The code allows the number of fds supported by the fdarray (fdtable->max_fds) to differ from the number of fds supported by each of the fdsets (fdtable->max_fdset). In practice, it is wasteful for these two sizes to differ: whenever we hit a limit on the smaller-capacity structure, we will reallocate the entire fdtable and all the dynamic arrays within it, so any delta in the memory used by the larger-capacity structure will never be touched at all. Rather than hogging this excess, we shouldn't even allocate it in the first place, and keep the capacities of the fdarray and the fdsets equal. This patch removes fdtable->max_fdset. As an added bonus, most of the supporting code becomes simpler. Signed-off-by: Vadim Lobanov <vlobanov@speakeasy.net> Cc: Christoph Hellwig <hch@lst.de> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Dipankar Sarma <dipankar@in.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/file.c')
-rw-r--r--fs/file.c56
1 files changed, 22 insertions, 34 deletions
diff --git a/fs/file.c b/fs/file.c
index 51aef675470f..fb3d2038dc21 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -68,8 +68,8 @@ void free_fd_array(struct file **array, int num)
68 68
69static void __free_fdtable(struct fdtable *fdt) 69static 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
137void free_fdtable(struct fdtable *fdt) 135void 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
202void free_fdset(fd_set *array, int num) 197void 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;
261out2:
262 nfds = fdt->max_fdset;
263out: 252out:
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 */