Skip to content

Commit 4edaeba

Browse files
Al Virogregkh
authored andcommitted
alloc_fdtable(): change calling conventions.
[ Upstream commit 1d3b4be ] First of all, tell it how many slots do we want, not which slot is wanted. It makes one caller (dup_fd()) more straightforward and doesn't harm another (expand_fdtable()). Furthermore, make it return ERR_PTR() on failure rather than returning NULL. Simplifies the callers. Simplify the size calculation, while we are at it - note that we always have slots_wanted greater than BITS_PER_LONG. What the rules boil down to is * use the smallest power of two large enough to give us that many slots * on 32bit skip 64 and 128 - the minimal capacity we want there is 256 slots (i.e. 1Kb fd array). * on 64bit don't skip anything, the minimal capacity is 128 - and we'll never be asked for 64 or less. 128 slots means 1Kb fd array, again. * on 128bit, if that ever happens, don't skip anything - we'll never be asked for 128 or less, so the fd array allocation will be at least 2Kb. Reviewed-by: Christian Brauner <brauner@kernel.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 51e8531 commit 4edaeba

File tree

1 file changed

+29
-46
lines changed

1 file changed

+29
-46
lines changed

fs/file.c

Lines changed: 29 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -90,41 +90,44 @@ static void copy_fdtable(struct fdtable *nfdt, struct fdtable *ofdt)
9090
* 'unsigned long' in some places, but simply because that is how the Linux
9191
* kernel bitmaps are defined to work: they are not "bits in an array of bytes",
9292
* they are very much "bits in an array of unsigned long".
93-
*
94-
* The ALIGN(nr, BITS_PER_LONG) here is for clarity: since we just multiplied
95-
* by that "1024/sizeof(ptr)" before, we already know there are sufficient
96-
* clear low bits. Clang seems to realize that, gcc ends up being confused.
97-
*
98-
* On a 128-bit machine, the ALIGN() would actually matter. In the meantime,
99-
* let's consider it documentation (and maybe a test-case for gcc to improve
100-
* its code generation ;)
10193
*/
102-
static struct fdtable * alloc_fdtable(unsigned int nr)
94+
static struct fdtable *alloc_fdtable(unsigned int slots_wanted)
10395
{
10496
struct fdtable *fdt;
97+
unsigned int nr;
10598
void *data;
10699

107100
/*
108101
* Figure out how many fds we actually want to support in this fdtable.
109102
* Allocation steps are keyed to the size of the fdarray, since it
110103
* grows far faster than any of the other dynamic data. We try to fit
111104
* the fdarray into comfortable page-tuned chunks: starting at 1024B
112-
* and growing in powers of two from there on.
105+
* and growing in powers of two from there on. Since we called only
106+
* with slots_wanted > BITS_PER_LONG (embedded instance in files->fdtab
107+
* already gives BITS_PER_LONG slots), the above boils down to
108+
* 1. use the smallest power of two large enough to give us that many
109+
* slots.
110+
* 2. on 32bit skip 64 and 128 - the minimal capacity we want there is
111+
* 256 slots (i.e. 1Kb fd array).
112+
* 3. on 64bit don't skip anything, 1Kb fd array means 128 slots there
113+
* and we are never going to be asked for 64 or less.
113114
*/
114-
nr /= (1024 / sizeof(struct file *));
115-
nr = roundup_pow_of_two(nr + 1);
116-
nr *= (1024 / sizeof(struct file *));
117-
nr = ALIGN(nr, BITS_PER_LONG);
115+
if (IS_ENABLED(CONFIG_32BIT) && slots_wanted < 256)
116+
nr = 256;
117+
else
118+
nr = roundup_pow_of_two(slots_wanted);
118119
/*
119120
* Note that this can drive nr *below* what we had passed if sysctl_nr_open
120-
* had been set lower between the check in expand_files() and here. Deal
121-
* with that in caller, it's cheaper that way.
121+
* had been set lower between the check in expand_files() and here.
122122
*
123123
* We make sure that nr remains a multiple of BITS_PER_LONG - otherwise
124124
* bitmaps handling below becomes unpleasant, to put it mildly...
125125
*/
126-
if (unlikely(nr > sysctl_nr_open))
127-
nr = ((sysctl_nr_open - 1) | (BITS_PER_LONG - 1)) + 1;
126+
if (unlikely(nr > sysctl_nr_open)) {
127+
nr = round_down(sysctl_nr_open, BITS_PER_LONG);
128+
if (nr < slots_wanted)
129+
return ERR_PTR(-EMFILE);
130+
}
128131

129132
/*
130133
* Check if the allocation size would exceed INT_MAX. kvmalloc_array()
@@ -168,7 +171,7 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
168171
out_fdt:
169172
kfree(fdt);
170173
out:
171-
return NULL;
174+
return ERR_PTR(-ENOMEM);
172175
}
173176

174177
/*
@@ -185,7 +188,7 @@ static int expand_fdtable(struct files_struct *files, unsigned int nr)
185188
struct fdtable *new_fdt, *cur_fdt;
186189

187190
spin_unlock(&files->file_lock);
188-
new_fdt = alloc_fdtable(nr);
191+
new_fdt = alloc_fdtable(nr + 1);
189192

190193
/* make sure all fd_install() have seen resize_in_progress
191194
* or have finished their rcu_read_lock_sched() section.
@@ -194,16 +197,8 @@ static int expand_fdtable(struct files_struct *files, unsigned int nr)
194197
synchronize_rcu();
195198

196199
spin_lock(&files->file_lock);
197-
if (!new_fdt)
198-
return -ENOMEM;
199-
/*
200-
* extremely unlikely race - sysctl_nr_open decreased between the check in
201-
* caller and alloc_fdtable(). Cheaper to catch it here...
202-
*/
203-
if (unlikely(new_fdt->max_fds <= nr)) {
204-
__free_fdtable(new_fdt);
205-
return -EMFILE;
206-
}
200+
if (IS_ERR(new_fdt))
201+
return PTR_ERR(new_fdt);
207202
cur_fdt = files_fdtable(files);
208203
BUG_ON(nr < cur_fdt->max_fds);
209204
copy_fdtable(new_fdt, cur_fdt);
@@ -322,7 +317,6 @@ struct files_struct *dup_fd(struct files_struct *oldf, struct fd_range *punch_ho
322317
struct file **old_fds, **new_fds;
323318
unsigned int open_files, i;
324319
struct fdtable *old_fdt, *new_fdt;
325-
int error;
326320

327321
newf = kmem_cache_alloc(files_cachep, GFP_KERNEL);
328322
if (!newf)
@@ -354,17 +348,10 @@ struct files_struct *dup_fd(struct files_struct *oldf, struct fd_range *punch_ho
354348
if (new_fdt != &newf->fdtab)
355349
__free_fdtable(new_fdt);
356350

357-
new_fdt = alloc_fdtable(open_files - 1);
358-
if (!new_fdt) {
359-
error = -ENOMEM;
360-
goto out_release;
361-
}
362-
363-
/* beyond sysctl_nr_open; nothing to do */
364-
if (unlikely(new_fdt->max_fds < open_files)) {
365-
__free_fdtable(new_fdt);
366-
error = -EMFILE;
367-
goto out_release;
351+
new_fdt = alloc_fdtable(open_files);
352+
if (IS_ERR(new_fdt)) {
353+
kmem_cache_free(files_cachep, newf);
354+
return ERR_CAST(new_fdt);
368355
}
369356

370357
/*
@@ -413,10 +400,6 @@ struct files_struct *dup_fd(struct files_struct *oldf, struct fd_range *punch_ho
413400
rcu_assign_pointer(newf->fdt, new_fdt);
414401

415402
return newf;
416-
417-
out_release:
418-
kmem_cache_free(files_cachep, newf);
419-
return ERR_PTR(error);
420403
}
421404

422405
static struct fdtable *close_files(struct files_struct * files)

0 commit comments

Comments
 (0)