fs: remove dentry_lru_prune()
When pruning a dentry, its ancestor dentry can also be pruned. But the ancestor dentry does not go through dput(), so it does not get put on the dentry LRU. Hence associating d_prune with removing the dentry from the LRU is the wrong. The fix is remove dentry_lru_prune(). Call file system's d_prune() callback directly when pruning dentries. Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
6b13eb1baa
commit
61572bb1f4
1 changed files with 9 additions and 22 deletions
31
fs/dcache.c
31
fs/dcache.c
|
@ -337,23 +337,6 @@ static void dentry_lru_del(struct dentry *dentry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Remove a dentry that is unreferenced and about to be pruned
|
|
||||||
* (unhashed and destroyed) from the LRU, and inform the file system.
|
|
||||||
* This wrapper should be called _prior_ to unhashing a victim dentry.
|
|
||||||
*/
|
|
||||||
static void dentry_lru_prune(struct dentry *dentry)
|
|
||||||
{
|
|
||||||
if (!list_empty(&dentry->d_lru)) {
|
|
||||||
if (dentry->d_flags & DCACHE_OP_PRUNE)
|
|
||||||
dentry->d_op->d_prune(dentry);
|
|
||||||
|
|
||||||
spin_lock(&dcache_lru_lock);
|
|
||||||
__dentry_lru_del(dentry);
|
|
||||||
spin_unlock(&dcache_lru_lock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dentry_lru_move_list(struct dentry *dentry, struct list_head *list)
|
static void dentry_lru_move_list(struct dentry *dentry, struct list_head *list)
|
||||||
{
|
{
|
||||||
spin_lock(&dcache_lru_lock);
|
spin_lock(&dcache_lru_lock);
|
||||||
|
@ -486,11 +469,13 @@ static inline struct dentry *dentry_kill(struct dentry *dentry, int ref)
|
||||||
if (ref)
|
if (ref)
|
||||||
dentry->d_count--;
|
dentry->d_count--;
|
||||||
/*
|
/*
|
||||||
* if dentry was on the d_lru list delete it from there.
|
|
||||||
* inform the fs via d_prune that this dentry is about to be
|
* inform the fs via d_prune that this dentry is about to be
|
||||||
* unhashed and destroyed.
|
* unhashed and destroyed.
|
||||||
*/
|
*/
|
||||||
dentry_lru_prune(dentry);
|
if (dentry->d_flags & DCACHE_OP_PRUNE)
|
||||||
|
dentry->d_op->d_prune(dentry);
|
||||||
|
|
||||||
|
dentry_lru_del(dentry);
|
||||||
/* if it was on the hash then remove it */
|
/* if it was on the hash then remove it */
|
||||||
__d_drop(dentry);
|
__d_drop(dentry);
|
||||||
return d_kill(dentry, parent);
|
return d_kill(dentry, parent);
|
||||||
|
@ -919,11 +904,13 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* remove the dentry from the lru, and inform
|
* inform the fs that this dentry is about to be
|
||||||
* the fs that this dentry is about to be
|
|
||||||
* unhashed and destroyed.
|
* unhashed and destroyed.
|
||||||
*/
|
*/
|
||||||
dentry_lru_prune(dentry);
|
if (dentry->d_flags & DCACHE_OP_PRUNE)
|
||||||
|
dentry->d_op->d_prune(dentry);
|
||||||
|
|
||||||
|
dentry_lru_del(dentry);
|
||||||
__d_shrink(dentry);
|
__d_shrink(dentry);
|
||||||
|
|
||||||
if (dentry->d_count != 0) {
|
if (dentry->d_count != 0) {
|
||||||
|
|
Loading…
Reference in a new issue