@@ -272,20 +272,6 @@ static inline bool fd_is_open(unsigned int fd, const struct fdtable *fdt)
return test_bit(fd, fdt->open_fds);
}
-static unsigned int count_open_files(struct fdtable *fdt)
-{
- unsigned int size = fdt->max_fds;
- unsigned int i;
-
- /* Find the last open fd */
- for (i = size / BITS_PER_LONG; i > 0; ) {
- if (fdt->open_fds[--i])
- break;
- }
- i = (i + 1) * BITS_PER_LONG;
- return i;
-}
-
/*
* Note that a sane fdtable size always has to be a multiple of
* BITS_PER_LONG, since we have bitmaps that are sized by this.
@@ -297,16 +283,33 @@ static unsigned int count_open_files(struct fdtable *fdt)
*
* Rather than make close_range() have to worry about this,
* just make that BITS_PER_LONG alignment be part of a sane
- * fdtable size. Becuase that's really what it is.
+ * fdtable size. Because that's really what it is.
*/
static unsigned int sane_fdtable_size(struct fdtable *fdt, unsigned int max_fds)
{
- unsigned int count;
+ const unsigned int min_words = BITS_TO_LONGS(NR_OPEN_DEFAULT); // 1
+ unsigned long mask;
+ unsigned int words;
+
+ if (max_fds > fdt->max_fds)
+ max_fds = fdt->max_fds;
+
+ if (max_fds == NR_OPEN_DEFAULT)
+ return NR_OPEN_DEFAULT;
+
+ /*
+ * What follows is a simplified find_last_bit(). There's no point
+ * finding exact last bit, when we are going to round it up anyway.
+ */
+ words = BITS_TO_LONGS(max_fds);
+ mask = BITMAP_LAST_WORD_MASK(max_fds);
+
+ while (words > min_words && !(fdt->open_fds[words - 1] & mask)) {
+ mask = ~0UL;
+ words--;
+ }
- count = count_open_files(fdt);
- if (max_fds < NR_OPEN_DEFAULT)
- max_fds = NR_OPEN_DEFAULT;
- return ALIGN(min(count, max_fds), BITS_PER_LONG);
+ return words * BITS_PER_LONG;
}
/*
when given a max_fds argument lower than that current size (that can happen when called from close_range(..., CLOSE_RANGE_UNSHARE)), we can ignore all descriptors >= max_fds. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> --- fs/file.c | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-)