Commit ce08b62d authored by Oleg Nesterov's avatar Oleg Nesterov Committed by Al Viro

change close_files() to use rcu_dereference_raw(files->fdt)

put_files_struct() and close_files() do rcu_read_lock() to make
rcu_dereference_check_fdtable() happy.

This looks a bit ugly, files_fdtable() just reads the pointer,
we can simply use rcu_dereference_raw() to avoid the warning.

The patch also changes close_files() to return fdt, this avoids
another rcu_read_lock()/files_fdtable() in put_files_struct().

I think close_files() needs more cleanups:

	- we do not need xchg() exactly because we are the last
	  user of this files_struct

	- "if (file)" should be turned into WARN_ON(!file)
Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent a8d4b834
...@@ -348,21 +348,16 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp) ...@@ -348,21 +348,16 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
return NULL; return NULL;
} }
static void close_files(struct files_struct * files) static struct fdtable *close_files(struct files_struct * files)
{ {
int i, j;
struct fdtable *fdt;
j = 0;
/* /*
* It is safe to dereference the fd table without RCU or * It is safe to dereference the fd table without RCU or
* ->file_lock because this is the last reference to the * ->file_lock because this is the last reference to the
* files structure. But use RCU to shut RCU-lockdep up. * files structure.
*/ */
rcu_read_lock(); struct fdtable *fdt = rcu_dereference_raw(files->fdt);
fdt = files_fdtable(files); int i, j = 0;
rcu_read_unlock();
for (;;) { for (;;) {
unsigned long set; unsigned long set;
i = j * BITS_PER_LONG; i = j * BITS_PER_LONG;
...@@ -381,6 +376,8 @@ static void close_files(struct files_struct * files) ...@@ -381,6 +376,8 @@ static void close_files(struct files_struct * files)
set >>= 1; set >>= 1;
} }
} }
return fdt;
} }
struct files_struct *get_files_struct(struct task_struct *task) struct files_struct *get_files_struct(struct task_struct *task)
...@@ -398,14 +395,9 @@ struct files_struct *get_files_struct(struct task_struct *task) ...@@ -398,14 +395,9 @@ struct files_struct *get_files_struct(struct task_struct *task)
void put_files_struct(struct files_struct *files) void put_files_struct(struct files_struct *files)
{ {
struct fdtable *fdt;
if (atomic_dec_and_test(&files->count)) { if (atomic_dec_and_test(&files->count)) {
close_files(files); struct fdtable *fdt = close_files(files);
/* not really needed, since nobody can see us */
rcu_read_lock();
fdt = files_fdtable(files);
rcu_read_unlock();
/* free the arrays if they are not embedded */ /* free the arrays if they are not embedded */
if (fdt != &files->fdtab) if (fdt != &files->fdtab)
__free_fdtable(fdt); __free_fdtable(fdt);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment