https://github.com/torvalds/linux
Revision 046b961b45f93a92e4c70525a12f3d378bced130 authored by Al Viro on 29 May 2014, 12:54:52 UTC, committed by Al Viro on 30 May 2014, 15:03:21 UTC
The cause of livelocks there is that we are taking ->d_lock on
dentry and its parent in the wrong order, forcing us to use
trylock on the parent's one.  d_walk() takes them in the right
order, and unfortunately it's not hard to create a situation
when shrink_dentry_list() can't make progress since trylock
keeps failing, and shrink_dcache_parent() or check_submounts_and_drop()
keeps calling d_walk() disrupting the very shrink_dentry_list() it's
waiting for.

Solution is straightforward - if that trylock fails, let's unlock
the dentry itself and take locks in the right order.  We need to
stabilize ->d_parent without holding ->d_lock, but that's doable
using RCU.  And we'd better do that in the very beginning of the
loop in shrink_dentry_list(), since the checks on refcount, etc.
would need to be redone anyway.

That deals with a half of the problem - killing dentries on the
shrink list itself.  Another one (dropping their parents) is
in the next commit.

locking parent is interesting - it would be easy to do rcu_read_lock(),
lock whatever we think is a parent, lock dentry itself and check
if the parent is still the right one.  Except that we need to check
that *before* locking the dentry, or we are risking taking ->d_lock
out of order.  Fortunately, once the D1 is locked, we can check if
D2->d_parent is equal to D1 without the need to lock D2; D2->d_parent
can start or stop pointing to D1 only under D1->d_lock, so taking
D1->d_lock is enough.  In other words, the right solution is
rcu_read_lock/lock what looks like parent right now/check if it's
still our parent/rcu_read_unlock/lock the child.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
1 parent ff2fde9
History
Tip revision: 046b961b45f93a92e4c70525a12f3d378bced130 authored by Al Viro on 29 May 2014, 12:54:52 UTC
shrink_dentry_list(): take parent's ->d_lock earlier
Tip revision: 046b961
File Mode Size
Documentation
arch
block
crypto
drivers
firmware
fs
include
init
ipc
kernel
lib
mm
net
samples
scripts
security
sound
tools
usr
virt
.gitignore -rw-r--r-- 1.1 KB
.mailmap -rw-r--r-- 4.4 KB
COPYING -rw-r--r-- 18.3 KB
CREDITS -rw-r--r-- 93.6 KB
Kbuild -rw-r--r-- 2.5 KB
Kconfig -rw-r--r-- 252 bytes
MAINTAINERS -rw-r--r-- 271.9 KB
Makefile -rw-r--r-- 50.5 KB
README -rw-r--r-- 18.3 KB
REPORTING-BUGS -rw-r--r-- 7.3 KB

README

back to top