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: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Родитель
a8d4b8345e
Коммит
ce08b62d18
26
fs/file.c
26
fs/file.c
|
@ -348,21 +348,16 @@ out:
|
|||
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
|
||||
* ->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();
|
||||
fdt = files_fdtable(files);
|
||||
rcu_read_unlock();
|
||||
struct fdtable *fdt = rcu_dereference_raw(files->fdt);
|
||||
int i, j = 0;
|
||||
|
||||
for (;;) {
|
||||
unsigned long set;
|
||||
i = j * BITS_PER_LONG;
|
||||
|
@ -381,6 +376,8 @@ static void close_files(struct files_struct * files)
|
|||
set >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return fdt;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct fdtable *fdt;
|
||||
|
||||
if (atomic_dec_and_test(&files->count)) {
|
||||
close_files(files);
|
||||
/* not really needed, since nobody can see us */
|
||||
rcu_read_lock();
|
||||
fdt = files_fdtable(files);
|
||||
rcu_read_unlock();
|
||||
struct fdtable *fdt = close_files(files);
|
||||
|
||||
/* free the arrays if they are not embedded */
|
||||
if (fdt != &files->fdtab)
|
||||
__free_fdtable(fdt);
|
||||
|
|
Загрузка…
Ссылка в новой задаче