introduce __fcheck_files() to fix rcu_dereference_check_fdtable(), kill rcu_my_thread...
authorOleg Nesterov <oleg@redhat.com>
Sat, 11 Jan 2014 18:19:32 +0000 (19:19 +0100)
committerAl Viro <viro@zeniv.linux.org.uk>
Sat, 25 Jan 2014 08:14:36 +0000 (03:14 -0500)
commita8d4b8345e0ee48b732126d980efaf0dc373e2b0
tree4bdfc52ef4ad176f54e4ce7b81091c0fbef0fd04
parent2ccdc413196b43a02bb68b46be5b68850904e9ea
introduce __fcheck_files() to fix rcu_dereference_check_fdtable(), kill rcu_my_thread_group_empty()

rcu_dereference_check_fdtable() looks very wrong,

1. rcu_my_thread_group_empty() was added by 844b9a8707f1 "vfs: fix
   RCU-lockdep false positive due to /proc" but it doesn't really
   fix the problem. A CLONE_THREAD (without CLONE_FILES) task can
   hit the same race with get_files_struct().

   And otoh rcu_my_thread_group_empty() can suppress the correct
   warning if the caller is the CLONE_FILES (without CLONE_THREAD)
   task.

2. files->count == 1 check is not really right too. Even if this
   files_struct is not shared it is not safe to access it lockless
   unless the caller is the owner.

   Otoh, this check is sub-optimal. files->count == 0 always means
   it is safe to use it lockless even if files != current->files,
   but put_files_struct() has to take rcu_read_lock(). See the next
   patch.

This patch removes the buggy checks and turns fcheck_files() into
__fcheck_files() which uses rcu_dereference_raw(), the "unshared"
callers, fget_light() and fget_raw_light(), can use it to avoid
the warning from RCU-lockdep.

fcheck_files() is trivially reimplemented as rcu_lockdep_assert()
plus __fcheck_files().

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/file.c
include/linux/fdtable.h
include/linux/rcupdate.h
kernel/rcu/update.c