Skip to content

Commit dccf19b

Browse files
committed
Merge: fs: improve fd allocation performance
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/1019 JIRA: https://issues.redhat.com/browse/RHEL-38569 Upstream status: Linus Back port patch series that improves the performance of fd allocation performance quite a bit. I investigated what it would take to include commit dc530c4 since it seemed worthwhile due to the addition of the rcu_*() functions in the updated debug statements. To include this cleanly pulls in at least 4 commits (probably several more if I work though it fully) that aren't all small changes from a series leading to commit b8ea429 (for those who would like to check the implications). The added complexity of several patches that look unrelated to the request didn't seem worth it to me but if anyone feels strongly about leaving these out I'll reconsider. Omitted-Fix: dc530c4 ("fs: use debug-only asserts around fd allocation and install") Signed-off-by: Ian Kent <ikent@redhat.com> Approved-by: Brian Foster <bfoster@redhat.com> Approved-by: Miklos Szeredi <mszeredi@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Julio Faracco <jfaracco@redhat.com>
2 parents 5129dc9 + 2d06b29 commit dccf19b

File tree

1 file changed

+26
-20
lines changed

1 file changed

+26
-20
lines changed

fs/file.c

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,9 @@ static inline void __set_open_fd(unsigned int fd, struct fdtable *fdt)
327327
static inline void __clear_open_fd(unsigned int fd, struct fdtable *fdt)
328328
{
329329
__clear_bit(fd, fdt->open_fds);
330-
__clear_bit(fd / BITS_PER_LONG, fdt->full_fds_bits);
330+
fd /= BITS_PER_LONG;
331+
if (test_bit(fd, fdt->full_fds_bits))
332+
__clear_bit(fd, fdt->full_fds_bits);
331333
}
332334

333335
static inline bool fd_is_open(unsigned int fd, const struct fdtable *fdt)
@@ -533,6 +535,15 @@ static unsigned int find_next_fd(struct fdtable *fdt, unsigned int start)
533535
unsigned int maxfd = fdt->max_fds; /* always multiple of BITS_PER_LONG */
534536
unsigned int maxbit = maxfd / BITS_PER_LONG;
535537
unsigned int bitbit = start / BITS_PER_LONG;
538+
unsigned int bit;
539+
540+
/*
541+
* Try to avoid looking at the second level bitmap
542+
*/
543+
bit = find_next_zero_bit(&fdt->open_fds[bitbit], BITS_PER_LONG,
544+
start & (BITS_PER_LONG - 1));
545+
if (bit < BITS_PER_LONG)
546+
return bit + bitbit * BITS_PER_LONG;
536547

537548
bitbit = find_next_zero_bit(fdt->full_fds_bits, maxbit, bitbit) * BITS_PER_LONG;
538549
if (bitbit >= maxfd)
@@ -559,27 +570,29 @@ static int alloc_fd(unsigned start, unsigned end, unsigned flags)
559570
if (fd < files->next_fd)
560571
fd = files->next_fd;
561572

562-
if (fd < fdt->max_fds)
573+
if (likely(fd < fdt->max_fds))
563574
fd = find_next_fd(fdt, fd);
564575

565576
/*
566577
* N.B. For clone tasks sharing a files structure, this test
567578
* will limit the total number of files that can be opened.
568579
*/
569580
error = -EMFILE;
570-
if (fd >= end)
581+
if (unlikely(fd >= end))
571582
goto out;
572583

573-
error = expand_files(files, fd);
574-
if (error < 0)
575-
goto out;
584+
if (unlikely(fd >= fdt->max_fds)) {
585+
error = expand_files(files, fd);
586+
if (error < 0)
587+
goto out;
576588

577-
/*
578-
* If we needed to expand the fs array we
579-
* might have blocked - try again.
580-
*/
581-
if (error)
582-
goto repeat;
589+
/*
590+
* If we needed to expand the fs array we
591+
* might have blocked - try again.
592+
*/
593+
if (error)
594+
goto repeat;
595+
}
583596

584597
if (start <= files->next_fd)
585598
files->next_fd = fd + 1;
@@ -590,13 +603,6 @@ static int alloc_fd(unsigned start, unsigned end, unsigned flags)
590603
else
591604
__clear_close_on_exec(fd, fdt);
592605
error = fd;
593-
#if 1
594-
/* Sanity check */
595-
if (rcu_access_pointer(fdt->fd[fd]) != NULL) {
596-
printk(KERN_WARNING "alloc_fd: slot %d not NULL!\n", fd);
597-
rcu_assign_pointer(fdt->fd[fd], NULL);
598-
}
599-
#endif
600606

601607
out:
602608
spin_unlock(&files->file_lock);
@@ -662,7 +668,7 @@ void fd_install(unsigned int fd, struct file *file)
662668
rcu_read_unlock_sched();
663669
spin_lock(&files->file_lock);
664670
fdt = files_fdtable(files);
665-
BUG_ON(fdt->fd[fd] != NULL);
671+
WARN_ON(fdt->fd[fd] != NULL);
666672
rcu_assign_pointer(fdt->fd[fd], file);
667673
spin_unlock(&files->file_lock);
668674
return;

0 commit comments

Comments
 (0)