diff options
| author | Mateusz Guzik <mjguzik@gmail.com> | 2025-11-10 10:56:34 +0100 |
|---|---|---|
| committer | Christian Brauner <brauner@kernel.org> | 2025-11-12 12:19:09 +0100 |
| commit | 9eda581bfe8a1774390dd66f365a2e00a9d27a41 (patch) | |
| tree | d46caac5be98e09bf08634e6357cef1a5cdabf34 /fs/file.c | |
| parent | 21b561dab1406e63740ebe240c7b69f19e1bcf58 (diff) | |
| download | tip-9eda581bfe8a1774390dd66f365a2e00a9d27a41.tar.gz | |
fs: move fd_install() slowpath into a dedicated routine and provide commentary
On stock kernel gcc 14 emits avoidable register spillage:
endbr64
call ffffffff81374630 <__fentry__>
push %r13
push %r12
push %rbx
sub $0x8,%rsp
[snip]
Total fast path is 99 bytes.
Moving the slowpath out avoids it and shortens the fast path to 74
bytes.
Signed-off-by: Mateusz Guzik <mjguzik@gmail.com>
Link: https://patch.msgid.link/20251110095634.1433061-1-mjguzik@gmail.com
Signed-off-by: Christian Brauner <brauner@kernel.org>
Diffstat (limited to 'fs/file.c')
| -rw-r--r-- | fs/file.c | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/fs/file.c b/fs/file.c index 28743b742e3cf6..3f56890068aa2c 100644 --- a/fs/file.c +++ b/fs/file.c @@ -641,6 +641,34 @@ void put_unused_fd(unsigned int fd) EXPORT_SYMBOL(put_unused_fd); +/* + * Install a file pointer in the fd array while it is being resized. + * + * We need to make sure our update to the array does not get lost as the resizing + * thread can be copying the content as we modify it. + * + * We have two ways to do it: + * - go off CPU waiting for resize_in_progress to clear + * - take the spin lock + * + * The latter is trivial to implement and saves us from having to might_sleep() + * for debugging purposes. + * + * This is moved out of line from fd_install() to convince gcc to optimize that + * routine better. + */ +static void noinline fd_install_slowpath(unsigned int fd, struct file *file) +{ + struct files_struct *files = current->files; + struct fdtable *fdt; + + spin_lock(&files->file_lock); + fdt = files_fdtable(files); + VFS_BUG_ON(rcu_access_pointer(fdt->fd[fd]) != NULL); + rcu_assign_pointer(fdt->fd[fd], file); + spin_unlock(&files->file_lock); +} + /** * fd_install - install a file pointer in the fd array * @fd: file descriptor to install the file in @@ -658,14 +686,9 @@ void fd_install(unsigned int fd, struct file *file) return; rcu_read_lock_sched(); - if (unlikely(files->resize_in_progress)) { rcu_read_unlock_sched(); - spin_lock(&files->file_lock); - fdt = files_fdtable(files); - VFS_BUG_ON(rcu_access_pointer(fdt->fd[fd]) != NULL); - rcu_assign_pointer(fdt->fd[fd], file); - spin_unlock(&files->file_lock); + fd_install_slowpath(fd, file); return; } /* coupled with smp_wmb() in expand_fdtable() */ |
