Commit 8fd3395e authored by Al Viro's avatar Al Viro
Browse files

get rid of ...lookup...fdget_rcu() family



Once upon a time, predecessors of those used to do file lookup
without bumping a refcount, provided that caller held rcu_read_lock()
across the lookup and whatever it wanted to read from the struct
file found.  When struct file allocation switched to SLAB_TYPESAFE_BY_RCU,
that stopped being feasible and these primitives started to bump the
file refcount for lookup result, requiring the caller to call fput()
afterwards.

But that turned them pointless - e.g.
	rcu_read_lock();
	file = lookup_fdget_rcu(fd);
	rcu_read_unlock();
is equivalent to
	file = fget_raw(fd);
and all callers of lookup_fdget_rcu() are of that form.  Similarly,
task_lookup_fdget_rcu() calls can be replaced with calling fget_task().
task_lookup_next_fdget_rcu() doesn't have direct counterparts, but
its callers would be happier if we replaced it with an analogue that
deals with RCU internally.

Reviewed-by: default avatarChristian Brauner <brauner@kernel.org>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 8cf0b939
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -73,9 +73,7 @@ static struct spu_context *coredump_next_context(int *fd)
		return NULL;
	*fd = n - 1;

	rcu_read_lock();
	file = lookup_fdget_rcu(*fd);
	rcu_read_unlock();
	file = fget_raw(*fd);
	if (file) {
		ctx = SPUFS_I(file_inode(file))->i_ctx;
		get_spu_context(ctx);
+4 −24
Original line number Diff line number Diff line
@@ -1037,29 +1037,7 @@ struct file *fget_task(struct task_struct *task, unsigned int fd)
	return file;
}

struct file *lookup_fdget_rcu(unsigned int fd)
{
	return __fget_files_rcu(current->files, fd, 0);

}
EXPORT_SYMBOL_GPL(lookup_fdget_rcu);

struct file *task_lookup_fdget_rcu(struct task_struct *task, unsigned int fd)
{
	/* Must be called with rcu_read_lock held */
	struct files_struct *files;
	struct file *file = NULL;

	task_lock(task);
	files = task->files;
	if (files)
		file = __fget_files_rcu(files, fd, 0);
	task_unlock(task);

	return file;
}

struct file *task_lookup_next_fdget_rcu(struct task_struct *task, unsigned int *ret_fd)
struct file *fget_task_next(struct task_struct *task, unsigned int *ret_fd)
{
	/* Must be called with rcu_read_lock held */
	struct files_struct *files;
@@ -1069,17 +1047,19 @@ struct file *task_lookup_next_fdget_rcu(struct task_struct *task, unsigned int *
	task_lock(task);
	files = task->files;
	if (files) {
		rcu_read_lock();
		for (; fd < files_fdtable(files)->max_fds; fd++) {
			file = __fget_files_rcu(files, fd, 0);
			if (file)
				break;
		}
		rcu_read_unlock();
	}
	task_unlock(task);
	*ret_fd = fd;
	return file;
}
EXPORT_SYMBOL(task_lookup_next_fdget_rcu);
EXPORT_SYMBOL(fget_task_next);

/*
 * Lightweight file lookup - no refcnt increment if fd table isn't shared.
+2 −10
Original line number Diff line number Diff line
@@ -34,7 +34,6 @@
#include <linux/lockref.h>
#include <linux/rhashtable.h>
#include <linux/pid_namespace.h>
#include <linux/fdtable.h>
#include <linux/file.h>

#include "gfs2.h"
@@ -2768,25 +2767,18 @@ static struct file *gfs2_glockfd_next_file(struct gfs2_glockfd_iter *i)
		i->file = NULL;
	}

	rcu_read_lock();
	for(;; i->fd++) {
		struct inode *inode;

		i->file = task_lookup_next_fdget_rcu(i->task, &i->fd);
		i->file = fget_task_next(i->task, &i->fd);
		if (!i->file) {
			i->fd = 0;
			break;
		}

		inode = file_inode(i->file);
		if (inode->i_sb == i->sb)
		if (file_inode(i->file)->i_sb == i->sb)
			break;

		rcu_read_unlock();
		fput(i->file);
		rcu_read_lock();
	}
	rcu_read_unlock();
	return i->file;
}

+1 −4
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@
#include <linux/security.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/fdtable.h>
#include <linux/fsnotify_backend.h>

static int dir_notify_enable __read_mostly = 1;
@@ -347,9 +346,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned int arg)
		new_fsn_mark = NULL;
	}

	rcu_read_lock();
	f = lookup_fdget_rcu(fd);
	rcu_read_unlock();
	f = fget_raw(fd);

	/* if (f != filp) means that we lost a race and another task/thread
	 * actually closed the fd we are still playing with before we grabbed
+3 −9
Original line number Diff line number Diff line
@@ -116,9 +116,7 @@ static bool tid_fd_mode(struct task_struct *task, unsigned fd, fmode_t *mode)
{
	struct file *file;

	rcu_read_lock();
	file = task_lookup_fdget_rcu(task, fd);
	rcu_read_unlock();
	file = fget_task(task, fd);
	if (file) {
		*mode = file->f_mode;
		fput(file);
@@ -258,19 +256,17 @@ static int proc_readfd_common(struct file *file, struct dir_context *ctx,
	if (!dir_emit_dots(file, ctx))
		goto out;

	rcu_read_lock();
	for (fd = ctx->pos - 2;; fd++) {
		struct file *f;
		struct fd_data data;
		char name[10 + 1];
		unsigned int len;

		f = task_lookup_next_fdget_rcu(p, &fd);
		f = fget_task_next(p, &fd);
		ctx->pos = fd + 2LL;
		if (!f)
			break;
		data.mode = f->f_mode;
		rcu_read_unlock();
		fput(f);
		data.fd = fd;

@@ -278,11 +274,9 @@ static int proc_readfd_common(struct file *file, struct dir_context *ctx,
		if (!proc_fill_cache(file, ctx,
				     name, len, instantiate, p,
				     &data))
			goto out;
			break;
		cond_resched();
		rcu_read_lock();
	}
	rcu_read_unlock();
out:
	put_task_struct(p);
	return 0;
Loading