fs/file_table.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/fs/file_table.c b/fs/file_table.c index ee21b3da9d08..4fb87a0382d9 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -430,11 +430,33 @@ EXPORT_SYMBOL_GPL(flush_delayed_fput); static DECLARE_DELAYED_WORK(delayed_fput_work, delayed_fput); +/* + * Called for files that were never fully opened, and + * don't need the RCU-delayed freeing: they have never + * been accessed in any other context. + */ +static void fput_immediate(struct file *f) +{ + security_file_free(f); + put_cred(f->f_cred); + if (likely(!(f->f_mode & FMODE_NOACCOUNT))) + percpu_counter_dec(&nr_files); + if (unlikely(f->f_mode & FMODE_BACKING)) { + path_put(backing_file_real_path(f)); + kfree(backing_file(f)); + } else { + kmem_cache_free(filp_cachep, f); + } +} + 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_OPENED))) + return fput_immediate(file); + 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))