mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
[PATCH] files: files struct with RCU
Patch to eliminate struct files_struct.file_lock spinlock on the reader side and use rcu refcounting rcuref_xxx api for the f_count refcounter. The updates to the fdtable are done by allocating a new fdtable structure and setting files->fdt to point to the new structure. The fdtable structure is protected by RCU thereby allowing lock-free lookup. For fd arrays/sets that are vmalloced, we use keventd to free them since RCU callbacks can't sleep. A global list of fdtable to be freed is not scalable, so we use a per-cpu list. If keventd is already handling the current cpu's work, we use a timer to defer queueing of that work. Since the last publication, this patch has been re-written to avoid using explicit memory barriers and use rcu_assign_pointer(), rcu_dereference() premitives instead. This required that the fd information is kept in a separate structure (fdtable) and updated atomically. Signed-off-by: Dipankar Sarma <dipankar@in.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
6e72ad2c58
commit
ab2af1f500
10 changed files with 354 additions and 175 deletions
|
@ -9,6 +9,7 @@
|
|||
#include <linux/posix_types.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/rcupdate.h>
|
||||
|
||||
/*
|
||||
* The default fd array needs to be at least BITS_PER_LONG,
|
||||
|
@ -23,6 +24,9 @@ struct fdtable {
|
|||
struct file ** fd; /* current fd array */
|
||||
fd_set *close_on_exec;
|
||||
fd_set *open_fds;
|
||||
struct rcu_head rcu;
|
||||
struct files_struct *free_files;
|
||||
struct fdtable *next;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -31,13 +35,14 @@ struct fdtable {
|
|||
struct files_struct {
|
||||
atomic_t count;
|
||||
spinlock_t file_lock; /* Protects all the below members. Nests inside tsk->alloc_lock */
|
||||
struct fdtable *fdt;
|
||||
struct fdtable fdtab;
|
||||
fd_set close_on_exec_init;
|
||||
fd_set open_fds_init;
|
||||
struct file * fd_array[NR_OPEN_DEFAULT];
|
||||
};
|
||||
|
||||
#define files_fdtable(files) (&(files)->fdtab)
|
||||
#define files_fdtable(files) (rcu_dereference((files)->fdt))
|
||||
|
||||
extern void FASTCALL(__fput(struct file *));
|
||||
extern void FASTCALL(fput(struct file *));
|
||||
|
@ -65,6 +70,8 @@ extern fd_set *alloc_fdset(int);
|
|||
extern void free_fdset(fd_set *, int);
|
||||
|
||||
extern int expand_files(struct files_struct *, int nr);
|
||||
extern void free_fdtable(struct fdtable *fdt);
|
||||
extern void __init files_defer_init(void);
|
||||
|
||||
static inline struct file * fcheck_files(struct files_struct *files, unsigned int fd)
|
||||
{
|
||||
|
@ -72,7 +79,7 @@ static inline struct file * fcheck_files(struct files_struct *files, unsigned in
|
|||
struct fdtable *fdt = files_fdtable(files);
|
||||
|
||||
if (fd < fdt->max_fds)
|
||||
file = fdt->fd[fd];
|
||||
file = rcu_dereference(fdt->fd[fd]);
|
||||
return file;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue