Commit a76c1ead authored by Al Viro's avatar Al Viro Committed by Greg Kroah-Hartman

fold try_prune_one_dentry()

commit 5c47e6d0 upstream.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Cc: "Nicholas A. Bellinger" <nab@linux-iscsi.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 79575968
......@@ -788,47 +788,9 @@ void d_prune_aliases(struct inode *inode)
}
EXPORT_SYMBOL(d_prune_aliases);
/*
* Try to throw away a dentry - free the inode, dput the parent.
* Requires dentry->d_lock is held, and dentry->d_count == 0.
* Releases dentry->d_lock.
*
* This may fail if locks cannot be acquired no problem, just try again.
*/
static struct dentry * try_prune_one_dentry(struct dentry *dentry)
__releases(dentry->d_lock)
{
struct dentry *parent;
parent = dentry_kill(dentry, 0);
/*
* If dentry_kill returns NULL, we have nothing more to do.
* if it returns the same dentry, trylocks failed. In either
* case, just loop again.
*
* Otherwise, we need to prune ancestors too. This is necessary
* to prevent quadratic behavior of shrink_dcache_parent(), but
* is also expected to be beneficial in reducing dentry cache
* fragmentation.
*/
if (!parent)
return NULL;
if (parent == dentry)
return dentry;
/* Prune ancestors. */
dentry = parent;
while (dentry) {
if (lockref_put_or_lock(&dentry->d_lockref))
return NULL;
dentry = dentry_kill(dentry, 1);
}
return NULL;
}
static void shrink_dentry_list(struct list_head *list)
{
struct dentry *dentry;
struct dentry *dentry, *parent;
rcu_read_lock();
for (;;) {
......@@ -864,22 +826,35 @@ static void shrink_dentry_list(struct list_head *list)
}
rcu_read_unlock();
parent = dentry_kill(dentry, 0);
/*
* If 'try_to_prune()' returns a dentry, it will
* be the same one we passed in, and d_lock will
* have been held the whole time, so it will not
* have been added to any other lists. We failed
* to get the inode lock.
*
* We just add it back to the shrink list.
* If dentry_kill returns NULL, we have nothing more to do.
*/
dentry = try_prune_one_dentry(dentry);
rcu_read_lock();
if (dentry) {
if (!parent) {
rcu_read_lock();
continue;
}
if (unlikely(parent == dentry)) {
/*
* trylocks have failed and d_lock has been held the
* whole time, so it could not have been added to any
* other lists. Just add it back to the shrink list.
*/
rcu_read_lock();
d_shrink_add(dentry, list);
spin_unlock(&dentry->d_lock);
continue;
}
/*
* We need to prune ancestors too. This is necessary to prevent
* quadratic behavior of shrink_dcache_parent(), but is also
* expected to be beneficial in reducing dentry cache
* fragmentation.
*/
dentry = parent;
while (dentry && !lockref_put_or_lock(&dentry->d_lockref))
dentry = dentry_kill(dentry, 1);
rcu_read_lock();
}
rcu_read_unlock();
}
......
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