Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+9 −17
Original line number Original line Diff line number Diff line
@@ -348,21 +348,16 @@ out:
	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)
			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)


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);