Commit 29355c39 authored by Al Viro's avatar Al Viro

d_prune_alias(): just lock the parent and call __dentry_kill()

The only reason for games with ->d_prune() was __d_drop(), which
was needed only to force dput() into killing the sucker off.

Note that lock_parent() can be called under ->i_lock and won't
drop it, so dentry is safe from somebody managing to kill it
under us - it won't happen while we are holding ->i_lock.

__dentry_kill() is called only with ->d_lockref.count being 0
(here and when picked from shrink list) or 1 (dput() and dropping
the ancestors in shrink_dentry_list()), so it will never be called
twice - the first thing it's doing is making ->d_lockref.count
negative and once that happens, nothing will increment it.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent bbd51924
...@@ -770,21 +770,14 @@ void d_prune_aliases(struct inode *inode) ...@@ -770,21 +770,14 @@ void d_prune_aliases(struct inode *inode)
hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) { hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
spin_lock(&dentry->d_lock); spin_lock(&dentry->d_lock);
if (!dentry->d_lockref.count) { if (!dentry->d_lockref.count) {
/* struct dentry *parent = lock_parent(dentry);
* inform the fs via d_prune that this dentry if (likely(!dentry->d_lockref.count)) {
* is about to be unhashed and destroyed. __dentry_kill(dentry);
*/
if ((dentry->d_flags & DCACHE_OP_PRUNE) &&
!d_unhashed(dentry))
dentry->d_op->d_prune(dentry);
__dget_dlock(dentry);
__d_drop(dentry);
spin_unlock(&dentry->d_lock);
spin_unlock(&inode->i_lock);
dput(dentry);
goto restart; goto restart;
} }
if (parent)
spin_unlock(&parent->d_lock);
}
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
} }
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment