summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2023-11-26 02:08:34 +0000
committerChristian Brauner <brauner@kernel.org>2023-12-12 14:24:09 +0100
commit7cb537b6f6d7d6529be04139178f929d9a63b918 (patch)
tree21261fb352f5a3c788e01b5d418869225b17ea54 /fs
parentb85ea95d086471afb4ad062012a4d73cd328fa86 (diff)
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')
-rw-r--r--fs/file_table.c16
-rw-r--r--fs/internal.h1
-rw-r--r--fs/namei.c5
3 files changed, 5 insertions, 17 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))
diff --git a/fs/internal.h b/fs/internal.h
index 58e43341aebf..273e6fd40d1b 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -94,7 +94,6 @@ extern void chroot_fs_refs(const struct path *, const struct path *);
struct file *alloc_empty_file(int flags, const struct cred *cred);
struct file *alloc_empty_file_noaccount(int flags, const struct cred *cred);
struct file *alloc_empty_backing_file(int flags, const struct cred *cred);
-void release_empty_file(struct file *f);
static inline void file_put_write_access(struct file *file)
{
diff --git a/fs/namei.c b/fs/namei.c
index 71c13b2990b4..f0ead1858267 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3785,10 +3785,7 @@ static struct file *path_openat(struct nameidata *nd,
WARN_ON(1);
error = -EINVAL;
}
- if (unlikely(file->f_mode & FMODE_OPENED))
- fput(file);
- else
- release_empty_file(file);
+ fput(file);
if (error == -EOPENSTALE) {
if (flags & LOOKUP_RCU)
error = -ECHILD;