Unverified Commit 7cb537b6 authored by Al Viro's avatar Al Viro Committed by Christian Brauner
Browse files

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: default avatarAl 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: default avatarChristian Brauner <brauner@kernel.org>
parent b85ea95d
Loading
Loading
Loading
Loading
+4 −12
Original line number Diff line number Diff line
@@ -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))
+0 −1
Original line number Diff line number Diff line
@@ -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)
{
+1 −4
Original line number Diff line number Diff line
@@ -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);
	if (error == -EOPENSTALE) {
		if (flags & LOOKUP_RCU)
			error = -ECHILD;