Commit 0e3efbd1 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Fix and clean up DCACHE_REFERENCED usage

From: Maneesh Soni <maneesh@in.ibm.com>

This patch changes the way DCACHE_REFERENCED flag is used. It
got messed up in dcache_rcu iterations. I hope this will be ok now.

The flag was meant to be advisory flag which is used while
prune_dcache() so as not to free dentries which have recently
entered d_lru list. At first pass in prune_dcache the dentries
marked DCACHE_REFERENCED are left with the flag reset. and they
are freed in the next pass.

So, now we mark the dentry as DCACHE_REFERENCED when it is first
entering the d_lru list in dput() and resetthe flag in prune_dcache().
If the flag remains reset in the next call to prune_dcache(), the
dentry is then freed.

Also I don't think any file system have to use this flag as it is taken
care by the dcache layer. The patch removes such code from a few of file
systems. Moreover these filesystems were anyway doing worng thing as they
were changing the flag out of dcache_lock.

Changes:
o dput() marks dentry DCACHE_REFERENCED when it is added to the dentry_unused
  list
o no need to set the flag in dget, dget_locked, d_lookup as these guys anyway
  increments the ref count.
o check the ref count in prune_dcache and use DCACHE_REFERENCED flag just for
  two stage aging.
o remove code for setting DACACHE_REFERENCED from reiserfs, fat, xfs and
  exportfs.
parent de8e3749
...@@ -155,12 +155,11 @@ void dput(struct dentry *dentry) ...@@ -155,12 +155,11 @@ void dput(struct dentry *dentry)
if (d_unhashed(dentry)) if (d_unhashed(dentry))
goto kill_it; goto kill_it;
if (list_empty(&dentry->d_lru)) { if (list_empty(&dentry->d_lru)) {
dentry->d_vfs_flags &= ~DCACHE_REFERENCED; dentry->d_vfs_flags |= DCACHE_REFERENCED;
list_add(&dentry->d_lru, &dentry_unused); list_add(&dentry->d_lru, &dentry_unused);
dentry_stat.nr_unused++; dentry_stat.nr_unused++;
} }
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
dentry->d_vfs_flags |= DCACHE_REFERENCED;
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
return; return;
...@@ -250,7 +249,6 @@ int d_invalidate(struct dentry * dentry) ...@@ -250,7 +249,6 @@ int d_invalidate(struct dentry * dentry)
static inline struct dentry * __dget_locked(struct dentry *dentry) static inline struct dentry * __dget_locked(struct dentry *dentry)
{ {
atomic_inc(&dentry->d_count); atomic_inc(&dentry->d_count);
dentry->d_vfs_flags |= DCACHE_REFERENCED;
if (atomic_read(&dentry->d_count) == 1) { if (atomic_read(&dentry->d_count) == 1) {
dentry_stat.nr_unused--; dentry_stat.nr_unused--;
list_del_init(&dentry->d_lru); list_del_init(&dentry->d_lru);
...@@ -379,17 +377,16 @@ static void prune_dcache(int count) ...@@ -379,17 +377,16 @@ static void prune_dcache(int count)
dentry = list_entry(tmp, struct dentry, d_lru); dentry = list_entry(tmp, struct dentry, d_lru);
spin_lock(&dentry->d_lock); spin_lock(&dentry->d_lock);
/* leave inuse dentries */
if (atomic_read(&dentry->d_count)) {
spin_unlock(&dentry->d_lock);
continue;
}
/* If the dentry was recently referenced, don't free it. */ /* If the dentry was recently referenced, don't free it. */
if (dentry->d_vfs_flags & DCACHE_REFERENCED) { if (dentry->d_vfs_flags & DCACHE_REFERENCED) {
dentry->d_vfs_flags &= ~DCACHE_REFERENCED; dentry->d_vfs_flags &= ~DCACHE_REFERENCED;
/* don't add non zero d_count dentries
* back to d_lru list
*/
if (!atomic_read(&dentry->d_count)) {
list_add(&dentry->d_lru, &dentry_unused); list_add(&dentry->d_lru, &dentry_unused);
dentry_stat.nr_unused++; dentry_stat.nr_unused++;
}
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
continue; continue;
} }
...@@ -1027,7 +1024,6 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name) ...@@ -1027,7 +1024,6 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name)
if (likely(move_count == dentry->d_move_count)) { if (likely(move_count == dentry->d_move_count)) {
if (!d_unhashed(dentry)) { if (!d_unhashed(dentry)) {
atomic_inc(&dentry->d_count); atomic_inc(&dentry->d_count);
dentry->d_vfs_flags |= DCACHE_REFERENCED;
found = dentry; found = dentry;
} }
} }
......
...@@ -91,7 +91,6 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent, ...@@ -91,7 +91,6 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
if (dentry != result && if (dentry != result &&
acceptable(context, dentry)) { acceptable(context, dentry)) {
dput(result); dput(result);
dentry->d_vfs_flags |= DCACHE_REFERENCED;
return dentry; return dentry;
} }
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
...@@ -271,7 +270,6 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent, ...@@ -271,7 +270,6 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
if (dentry != result && if (dentry != result &&
acceptable(context, dentry)) { acceptable(context, dentry)) {
dput(result); dput(result);
dentry->d_vfs_flags |= DCACHE_REFERENCED;
return dentry; return dentry;
} }
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
...@@ -434,7 +432,6 @@ static struct dentry *export_iget(struct super_block *sb, unsigned long ino, __u ...@@ -434,7 +432,6 @@ static struct dentry *export_iget(struct super_block *sb, unsigned long ino, __u
iput(inode); iput(inode);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
result->d_vfs_flags |= DCACHE_REFERENCED;
return result; return result;
} }
......
...@@ -608,7 +608,6 @@ struct dentry *fat_get_dentry(struct super_block *sb, void *inump) ...@@ -608,7 +608,6 @@ struct dentry *fat_get_dentry(struct super_block *sb, void *inump)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
result->d_op = sb->s_root->d_op; result->d_op = sb->s_root->d_op;
result->d_vfs_flags |= DCACHE_REFERENCED;
return result; return result;
} }
......
...@@ -1260,7 +1260,6 @@ struct dentry *reiserfs_get_dentry(struct super_block *sb, void *vobjp) ...@@ -1260,7 +1260,6 @@ struct dentry *reiserfs_get_dentry(struct super_block *sb, void *vobjp)
iput(inode); iput(inode);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
result->d_vfs_flags |= DCACHE_REFERENCED;
return result; return result;
} }
......
...@@ -741,7 +741,6 @@ linvfs_get_dentry( ...@@ -741,7 +741,6 @@ linvfs_get_dentry(
iput(inode); iput(inode);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
result->d_vfs_flags |= DCACHE_REFERENCED;
return result; return result;
} }
......
...@@ -270,7 +270,6 @@ static inline struct dentry *dget(struct dentry *dentry) ...@@ -270,7 +270,6 @@ static inline struct dentry *dget(struct dentry *dentry)
if (!atomic_read(&dentry->d_count)) if (!atomic_read(&dentry->d_count))
BUG(); BUG();
atomic_inc(&dentry->d_count); atomic_inc(&dentry->d_count);
dentry->d_vfs_flags |= DCACHE_REFERENCED;
} }
return dentry; return dentry;
} }
......
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