summaryrefslogtreecommitdiff
path: root/include/linux/fdtable.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/fdtable.h')
-rw-r--r--include/linux/fdtable.h35
1 files changed, 21 insertions, 14 deletions
diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h
index 085197bd8812..70e8e21c0a30 100644
--- a/include/linux/fdtable.h
+++ b/include/linux/fdtable.h
@@ -59,29 +59,36 @@ struct files_struct {
struct file __rcu * fd_array[NR_OPEN_DEFAULT];
};
-#define rcu_dereference_check_fdtable(files, fdtfd) \
- (rcu_dereference_check((fdtfd), \
- lockdep_is_held(&(files)->file_lock) || \
- atomic_read(&(files)->count) == 1 || \
- rcu_my_thread_group_empty()))
-
-#define files_fdtable(files) \
- (rcu_dereference_check_fdtable((files), (files)->fdt))
-
struct file_operations;
struct vfsmount;
struct dentry;
extern void __init files_defer_init(void);
-static inline struct file * fcheck_files(struct files_struct *files, unsigned int fd)
+#define rcu_dereference_check_fdtable(files, fdtfd) \
+ rcu_dereference_check((fdtfd), lockdep_is_held(&(files)->file_lock))
+
+#define files_fdtable(files) \
+ rcu_dereference_check_fdtable((files), (files)->fdt)
+
+/*
+ * The caller must ensure that fd table isn't shared or hold rcu or file lock
+ */
+static inline struct file *__fcheck_files(struct files_struct *files, unsigned int fd)
{
- struct file * file = NULL;
- struct fdtable *fdt = files_fdtable(files);
+ struct fdtable *fdt = rcu_dereference_raw(files->fdt);
if (fd < fdt->max_fds)
- file = rcu_dereference_check_fdtable(files, fdt->fd[fd]);
- return file;
+ return rcu_dereference_raw(fdt->fd[fd]);
+ return NULL;
+}
+
+static inline struct file *fcheck_files(struct files_struct *files, unsigned int fd)
+{
+ rcu_lockdep_assert(rcu_read_lock_held() ||
+ lockdep_is_held(&files->file_lock),
+ "suspicious rcu_dereference_check() usage");
+ return __fcheck_files(files, fd);
}
/*