mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
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: Christian Brauner <brauner@kernel.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
8cf0b93919
commit
8fd3395ec9
@ -73,9 +73,7 @@ static struct spu_context *coredump_next_context(int *fd)
|
|||||||
return NULL;
|
return NULL;
|
||||||
*fd = n - 1;
|
*fd = n - 1;
|
||||||
|
|
||||||
rcu_read_lock();
|
file = fget_raw(*fd);
|
||||||
file = lookup_fdget_rcu(*fd);
|
|
||||||
rcu_read_unlock();
|
|
||||||
if (file) {
|
if (file) {
|
||||||
ctx = SPUFS_I(file_inode(file))->i_ctx;
|
ctx = SPUFS_I(file_inode(file))->i_ctx;
|
||||||
get_spu_context(ctx);
|
get_spu_context(ctx);
|
||||||
|
28
fs/file.c
28
fs/file.c
@ -1037,29 +1037,7 @@ struct file *fget_task(struct task_struct *task, unsigned int fd)
|
|||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct file *lookup_fdget_rcu(unsigned int fd)
|
struct file *fget_task_next(struct task_struct *task, unsigned int *ret_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)
|
|
||||||
{
|
{
|
||||||
/* Must be called with rcu_read_lock held */
|
/* Must be called with rcu_read_lock held */
|
||||||
struct files_struct *files;
|
struct files_struct *files;
|
||||||
@ -1069,17 +1047,19 @@ struct file *task_lookup_next_fdget_rcu(struct task_struct *task, unsigned int *
|
|||||||
task_lock(task);
|
task_lock(task);
|
||||||
files = task->files;
|
files = task->files;
|
||||||
if (files) {
|
if (files) {
|
||||||
|
rcu_read_lock();
|
||||||
for (; fd < files_fdtable(files)->max_fds; fd++) {
|
for (; fd < files_fdtable(files)->max_fds; fd++) {
|
||||||
file = __fget_files_rcu(files, fd, 0);
|
file = __fget_files_rcu(files, fd, 0);
|
||||||
if (file)
|
if (file)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
task_unlock(task);
|
task_unlock(task);
|
||||||
*ret_fd = fd;
|
*ret_fd = fd;
|
||||||
return file;
|
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.
|
* Lightweight file lookup - no refcnt increment if fd table isn't shared.
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
#include <linux/lockref.h>
|
#include <linux/lockref.h>
|
||||||
#include <linux/rhashtable.h>
|
#include <linux/rhashtable.h>
|
||||||
#include <linux/pid_namespace.h>
|
#include <linux/pid_namespace.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
|
|
||||||
#include "gfs2.h"
|
#include "gfs2.h"
|
||||||
@ -2768,25 +2767,18 @@ static struct file *gfs2_glockfd_next_file(struct gfs2_glockfd_iter *i)
|
|||||||
i->file = NULL;
|
i->file = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rcu_read_lock();
|
|
||||||
for(;; i->fd++) {
|
for(;; i->fd++) {
|
||||||
struct inode *inode;
|
i->file = fget_task_next(i->task, &i->fd);
|
||||||
|
|
||||||
i->file = task_lookup_next_fdget_rcu(i->task, &i->fd);
|
|
||||||
if (!i->file) {
|
if (!i->file) {
|
||||||
i->fd = 0;
|
i->fd = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
inode = file_inode(i->file);
|
if (file_inode(i->file)->i_sb == i->sb)
|
||||||
if (inode->i_sb == i->sb)
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
rcu_read_unlock();
|
|
||||||
fput(i->file);
|
fput(i->file);
|
||||||
rcu_read_lock();
|
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
|
||||||
return i->file;
|
return i->file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
#include <linux/security.h>
|
#include <linux/security.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/fsnotify_backend.h>
|
#include <linux/fsnotify_backend.h>
|
||||||
|
|
||||||
static int dir_notify_enable __read_mostly = 1;
|
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;
|
new_fsn_mark = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rcu_read_lock();
|
f = fget_raw(fd);
|
||||||
f = lookup_fdget_rcu(fd);
|
|
||||||
rcu_read_unlock();
|
|
||||||
|
|
||||||
/* if (f != filp) means that we lost a race and another task/thread
|
/* 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
|
* actually closed the fd we are still playing with before we grabbed
|
||||||
|
12
fs/proc/fd.c
12
fs/proc/fd.c
@ -116,9 +116,7 @@ static bool tid_fd_mode(struct task_struct *task, unsigned fd, fmode_t *mode)
|
|||||||
{
|
{
|
||||||
struct file *file;
|
struct file *file;
|
||||||
|
|
||||||
rcu_read_lock();
|
file = fget_task(task, fd);
|
||||||
file = task_lookup_fdget_rcu(task, fd);
|
|
||||||
rcu_read_unlock();
|
|
||||||
if (file) {
|
if (file) {
|
||||||
*mode = file->f_mode;
|
*mode = file->f_mode;
|
||||||
fput(file);
|
fput(file);
|
||||||
@ -258,19 +256,17 @@ static int proc_readfd_common(struct file *file, struct dir_context *ctx,
|
|||||||
if (!dir_emit_dots(file, ctx))
|
if (!dir_emit_dots(file, ctx))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
rcu_read_lock();
|
|
||||||
for (fd = ctx->pos - 2;; fd++) {
|
for (fd = ctx->pos - 2;; fd++) {
|
||||||
struct file *f;
|
struct file *f;
|
||||||
struct fd_data data;
|
struct fd_data data;
|
||||||
char name[10 + 1];
|
char name[10 + 1];
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
|
|
||||||
f = task_lookup_next_fdget_rcu(p, &fd);
|
f = fget_task_next(p, &fd);
|
||||||
ctx->pos = fd + 2LL;
|
ctx->pos = fd + 2LL;
|
||||||
if (!f)
|
if (!f)
|
||||||
break;
|
break;
|
||||||
data.mode = f->f_mode;
|
data.mode = f->f_mode;
|
||||||
rcu_read_unlock();
|
|
||||||
fput(f);
|
fput(f);
|
||||||
data.fd = fd;
|
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,
|
if (!proc_fill_cache(file, ctx,
|
||||||
name, len, instantiate, p,
|
name, len, instantiate, p,
|
||||||
&data))
|
&data))
|
||||||
goto out;
|
break;
|
||||||
cond_resched();
|
cond_resched();
|
||||||
rcu_read_lock();
|
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
|
||||||
out:
|
out:
|
||||||
put_task_struct(p);
|
put_task_struct(p);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -92,10 +92,6 @@ static inline struct file *files_lookup_fd_locked(struct files_struct *files, un
|
|||||||
return files_lookup_fd_raw(files, fd);
|
return files_lookup_fd_raw(files, fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct file *lookup_fdget_rcu(unsigned int fd);
|
|
||||||
struct file *task_lookup_fdget_rcu(struct task_struct *task, unsigned int fd);
|
|
||||||
struct file *task_lookup_next_fdget_rcu(struct task_struct *task, unsigned int *fd);
|
|
||||||
|
|
||||||
static inline bool close_on_exec(unsigned int fd, const struct files_struct *files)
|
static inline bool close_on_exec(unsigned int fd, const struct files_struct *files)
|
||||||
{
|
{
|
||||||
return test_bit(fd, files_fdtable(files)->close_on_exec);
|
return test_bit(fd, files_fdtable(files)->close_on_exec);
|
||||||
|
@ -72,6 +72,7 @@ static inline void fdput(struct fd fd)
|
|||||||
extern struct file *fget(unsigned int fd);
|
extern struct file *fget(unsigned int fd);
|
||||||
extern struct file *fget_raw(unsigned int fd);
|
extern struct file *fget_raw(unsigned int fd);
|
||||||
extern struct file *fget_task(struct task_struct *task, unsigned int fd);
|
extern struct file *fget_task(struct task_struct *task, unsigned int fd);
|
||||||
|
extern struct file *fget_task_next(struct task_struct *task, unsigned int *fd);
|
||||||
extern void __f_unlock_pos(struct file *);
|
extern void __f_unlock_pos(struct file *);
|
||||||
|
|
||||||
struct fd fdget(unsigned int fd);
|
struct fd fdget(unsigned int fd);
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#include <linux/namei.h>
|
#include <linux/namei.h>
|
||||||
#include <linux/pid_namespace.h>
|
#include <linux/pid_namespace.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/filter.h>
|
#include <linux/filter.h>
|
||||||
#include <linux/bpf_mem_alloc.h>
|
#include <linux/bpf_mem_alloc.h>
|
||||||
#include <linux/btf_ids.h>
|
#include <linux/btf_ids.h>
|
||||||
@ -286,17 +285,14 @@ again:
|
|||||||
curr_fd = 0;
|
curr_fd = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
rcu_read_lock();
|
f = fget_task_next(curr_task, &curr_fd);
|
||||||
f = task_lookup_next_fdget_rcu(curr_task, &curr_fd);
|
|
||||||
if (f) {
|
if (f) {
|
||||||
/* set info->fd */
|
/* set info->fd */
|
||||||
info->fd = curr_fd;
|
info->fd = curr_fd;
|
||||||
rcu_read_unlock();
|
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the current task is done, go to the next task */
|
/* the current task is done, go to the next task */
|
||||||
rcu_read_unlock();
|
|
||||||
put_task_struct(curr_task);
|
put_task_struct(curr_task);
|
||||||
|
|
||||||
if (info->common.type == BPF_TASK_ITER_TID) {
|
if (info->common.type == BPF_TASK_ITER_TID) {
|
||||||
|
@ -63,9 +63,7 @@ get_file_raw_ptr(struct task_struct *task, unsigned int idx)
|
|||||||
{
|
{
|
||||||
struct file *file;
|
struct file *file;
|
||||||
|
|
||||||
rcu_read_lock();
|
file = fget_task(task, idx);
|
||||||
file = task_lookup_fdget_rcu(task, idx);
|
|
||||||
rcu_read_unlock();
|
|
||||||
if (file)
|
if (file)
|
||||||
fput(file);
|
fput(file);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user