diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2023-11-26 03:08:34 +0100 |
---|---|---|
committer | Christian Brauner <brauner@kernel.org> | 2023-12-12 14:24:09 +0100 |
commit | 7cb537b6f6d7d6529be04139178f929d9a63b918 (patch) | |
tree | 21261fb352f5a3c788e01b5d418869225b17ea54 /fs/file_table.c | |
parent | Linux 6.7-rc1 (diff) | |
download | linux-7cb537b6f6d7d6529be04139178f929d9a63b918.tar.xz linux-7cb537b6f6d7d6529be04139178f929d9a63b918.zip |
file: massage cleanup of files that failed to open
A file that has never gotten FMODE_OPENED will never have RCU-accessed
references, its final fput() is equivalent to file_free() and if it
doesn't have FMODE_BACKING either, it can be done from any context and
won't need task_work treatment.
Now that we have SLAB_TYPESAFE_BY_RCU we can simplify this and have
other callers benefit. All of that can be achieved easier is to make
fput() recoginze that case and call file_free() directly.
No need to introduce a special primitive for that. It also allowed
things like failing dentry_open() could benefit from that as well.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
[Christian Brauner <brauner@kernel.org>: massage commit message]
Link: https://lore.kernel.org/r/20231126020834.GC38156@ZenIV
Signed-off-by: Christian Brauner <brauner@kernel.org>
Diffstat (limited to 'fs/file_table.c')
-rw-r--r-- | fs/file_table.c | 16 |
1 files changed, 4 insertions, 12 deletions
diff --git a/fs/file_table.c b/fs/file_table.c index de4a2915bfd4..6deac386486d 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -75,18 +75,6 @@ static inline void file_free(struct file *f) } } -void release_empty_file(struct file *f) -{ - WARN_ON_ONCE(f->f_mode & (FMODE_BACKING | FMODE_OPENED)); - if (atomic_long_dec_and_test(&f->f_count)) { - security_file_free(f); - put_cred(f->f_cred); - if (likely(!(f->f_mode & FMODE_NOACCOUNT))) - percpu_counter_dec(&nr_files); - kmem_cache_free(filp_cachep, f); - } -} - /* * Return the total number of open files in the system */ @@ -445,6 +433,10 @@ void fput(struct file *file) if (atomic_long_dec_and_test(&file->f_count)) { struct task_struct *task = current; + if (unlikely(!(file->f_mode & (FMODE_BACKING | FMODE_OPENED)))) { + file_free(file); + return; + } if (likely(!in_interrupt() && !(task->flags & PF_KTHREAD))) { init_task_work(&file->f_rcuhead, ____fput); if (!task_work_add(task, &file->f_rcuhead, TWA_RESUME)) |