On Wed, Jun 11, 2014 at 06:32:58PM +0900, J. R. Okajima wrote: > > Al Viro: > > So I suspect that the right fix is a bit trickier - in addition to check > > on the fast path (i.e. when trylock gets us the lock on parent), we need > > to > > * get rcu_read_lock() before dropping ->d_lock. > > * check if dentry is already doomed right after taking rcu_read_lock(); > > if not, any value we might see in ->d_parent afterwards will point to object > > not freed until we drop rcu_read_lock. > > > > IOW, something like the delta below. Comments? > > I will try testing later. > For now, as a comment before testing, the patch looks weird for me. It > checks d_lockref.count twice during d_lockref.lock held. It must be the > same result, isn't it?
Right you are. So what we need is * check that thing once, as in your variant (I'd still prefer to check ->d_lockref.count instead of ->d_flags, but it's the same thing being tested) * ... and get rcu_read_lock() *before* dropping ->d_lock. The former guarantees that the address we are doing trylock on would be that of a live dentry. The latter makes sure that anything assigned to dentry->d_parent after we drop ->d_lock will not be freed until we drop rcu_read_lock. Signed-off-by: Al Viro <v...@zeniv.linux.org.uk> --- diff --git a/fs/dcache.c b/fs/dcache.c index be2bea8..e99c6f5 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -532,10 +532,12 @@ static inline struct dentry *lock_parent(struct dentry *dentry) struct dentry *parent = dentry->d_parent; if (IS_ROOT(dentry)) return NULL; + if (unlikely((int)dentry->d_lockref.count < 0)) + return NULL; if (likely(spin_trylock(&parent->d_lock))) return parent; - spin_unlock(&dentry->d_lock); rcu_read_lock(); + spin_unlock(&dentry->d_lock); again: parent = ACCESS_ONCE(dentry->d_parent); spin_lock(&parent->d_lock); -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/