Skip to content

Commit fc94368

Browse files
realwujingbrauner
authored andcommitted
fs/file: optimize close_range() complexity from O(N) to O(Sparse)
In close_range(), the kernel traditionally performs a linear scan over the [fd, max_fd] range, resulting in O(N) complexity where N is the range size. For processes with sparse FD tables, this is inefficient as it checks many unallocated slots. This patch optimizes __range_close() by using find_next_bit() on the open_fds bitmap to skip holes. This shifts the algorithmic complexity from O(Range Size) to O(Active FDs), providing a significant performance boost for large-range close operations on sparse file descriptor tables. Signed-off-by: Qiliang Yuan <realwujing@gmail.com> Signed-off-by: Qiliang Yuan <yuanql9@chinatelecom.cn> Link: https://patch.msgid.link/20260123081221.659125-1-realwujing@gmail.com Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent 6cbfdf8 commit fc94368

1 file changed

Lines changed: 8 additions & 2 deletions

File tree

fs/file.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -777,23 +777,29 @@ static inline void __range_close(struct files_struct *files, unsigned int fd,
777777
unsigned int max_fd)
778778
{
779779
struct file *file;
780+
struct fdtable *fdt;
780781
unsigned n;
781782

782783
spin_lock(&files->file_lock);
783-
n = last_fd(files_fdtable(files));
784+
fdt = files_fdtable(files);
785+
n = last_fd(fdt);
784786
max_fd = min(max_fd, n);
785787

786-
for (; fd <= max_fd; fd++) {
788+
for (fd = find_next_bit(fdt->open_fds, max_fd + 1, fd);
789+
fd <= max_fd;
790+
fd = find_next_bit(fdt->open_fds, max_fd + 1, fd + 1)) {
787791
file = file_close_fd_locked(files, fd);
788792
if (file) {
789793
spin_unlock(&files->file_lock);
790794
filp_close(file, files);
791795
cond_resched();
792796
spin_lock(&files->file_lock);
797+
fdt = files_fdtable(files);
793798
} else if (need_resched()) {
794799
spin_unlock(&files->file_lock);
795800
cond_resched();
796801
spin_lock(&files->file_lock);
802+
fdt = files_fdtable(files);
797803
}
798804
}
799805
spin_unlock(&files->file_lock);

0 commit comments

Comments
 (0)