diff options
| author | Andrew Morton <akpm@digeo.com> | 2003-04-20 00:26:14 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2003-04-20 00:26:14 -0700 |
| commit | 0e3efbd1ebf9b6f6b16cd5b68465f02dbe72dff0 (patch) | |
| tree | 3129a22f04ba3de1ff9f767f822b3dea4dfd5e01 | |
| parent | de8e3749bfc54556c3b9a40534fc2d3309ec84e6 (diff) | |
[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.
| -rw-r--r-- | fs/dcache.c | 20 | ||||
| -rw-r--r-- | fs/exportfs/expfs.c | 3 | ||||
| -rw-r--r-- | fs/fat/inode.c | 1 | ||||
| -rw-r--r-- | fs/reiserfs/inode.c | 1 | ||||
| -rw-r--r-- | fs/xfs/linux/xfs_super.c | 1 | ||||
| -rw-r--r-- | include/linux/dcache.h | 1 |
6 files changed, 8 insertions, 19 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index 59480fedd61a..9eec20e0ab20 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -155,12 +155,11 @@ repeat: if (d_unhashed(dentry)) goto kill_it; 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); dentry_stat.nr_unused++; } spin_unlock(&dentry->d_lock); - dentry->d_vfs_flags |= DCACHE_REFERENCED; spin_unlock(&dcache_lock); return; @@ -250,7 +249,6 @@ int d_invalidate(struct dentry * dentry) static inline struct dentry * __dget_locked(struct dentry *dentry) { atomic_inc(&dentry->d_count); - dentry->d_vfs_flags |= DCACHE_REFERENCED; if (atomic_read(&dentry->d_count) == 1) { dentry_stat.nr_unused--; list_del_init(&dentry->d_lru); @@ -379,17 +377,16 @@ static void prune_dcache(int count) dentry = list_entry(tmp, struct dentry, d_lru); 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 (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); - dentry_stat.nr_unused++; - } + list_add(&dentry->d_lru, &dentry_unused); + dentry_stat.nr_unused++; spin_unlock(&dentry->d_lock); continue; } @@ -1027,7 +1024,6 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name) if (likely(move_count == dentry->d_move_count)) { if (!d_unhashed(dentry)) { atomic_inc(&dentry->d_count); - dentry->d_vfs_flags |= DCACHE_REFERENCED; found = dentry; } } diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index 7264433b25fd..aae953bb9572 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c @@ -91,7 +91,6 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent, if (dentry != result && acceptable(context, dentry)) { dput(result); - dentry->d_vfs_flags |= DCACHE_REFERENCED; return dentry; } spin_lock(&dcache_lock); @@ -271,7 +270,6 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent, if (dentry != result && acceptable(context, dentry)) { dput(result); - dentry->d_vfs_flags |= DCACHE_REFERENCED; return dentry; } spin_lock(&dcache_lock); @@ -434,7 +432,6 @@ static struct dentry *export_iget(struct super_block *sb, unsigned long ino, __u iput(inode); return ERR_PTR(-ENOMEM); } - result->d_vfs_flags |= DCACHE_REFERENCED; return result; } diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 67548b28113d..866edb62fad5 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -608,7 +608,6 @@ struct dentry *fat_get_dentry(struct super_block *sb, void *inump) return ERR_PTR(-ENOMEM); } result->d_op = sb->s_root->d_op; - result->d_vfs_flags |= DCACHE_REFERENCED; return result; } diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 0536716aa84e..fb7f27f1f532 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1260,7 +1260,6 @@ struct dentry *reiserfs_get_dentry(struct super_block *sb, void *vobjp) iput(inode); return ERR_PTR(-ENOMEM); } - result->d_vfs_flags |= DCACHE_REFERENCED; return result; } diff --git a/fs/xfs/linux/xfs_super.c b/fs/xfs/linux/xfs_super.c index 662a43c90a1e..73ef4ec19e95 100644 --- a/fs/xfs/linux/xfs_super.c +++ b/fs/xfs/linux/xfs_super.c @@ -741,7 +741,6 @@ linvfs_get_dentry( iput(inode); return ERR_PTR(-ENOMEM); } - result->d_vfs_flags |= DCACHE_REFERENCED; return result; } diff --git a/include/linux/dcache.h b/include/linux/dcache.h index db979c3cf890..78fafd500123 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -270,7 +270,6 @@ static inline struct dentry *dget(struct dentry *dentry) if (!atomic_read(&dentry->d_count)) BUG(); atomic_inc(&dentry->d_count); - dentry->d_vfs_flags |= DCACHE_REFERENCED; } return dentry; } |
