summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Morton <akpm@digeo.com>2003-04-20 00:26:14 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2003-04-20 00:26:14 -0700
commit0e3efbd1ebf9b6f6b16cd5b68465f02dbe72dff0 (patch)
tree3129a22f04ba3de1ff9f767f822b3dea4dfd5e01
parentde8e3749bfc54556c3b9a40534fc2d3309ec84e6 (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.c20
-rw-r--r--fs/exportfs/expfs.c3
-rw-r--r--fs/fat/inode.c1
-rw-r--r--fs/reiserfs/inode.c1
-rw-r--r--fs/xfs/linux/xfs_super.c1
-rw-r--r--include/linux/dcache.h1
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;
}