[PATCH] Avoid race when updating nr_unused count of unused dentries.

From: NeilBrown
Date: Thu May 27 2004 - 23:39:26 EST



d_count == 1 is no guarantee that dentry is on the dentry_unused list,
even if it has just been incremented inside dcache_lock, as dput can
decrement at any time.

This test from Greg Banks is much safer, and is more transparently correct.

From: Greg Banks <gnb@xxxxxxxxxxxxxxxxx>
Signed-off-by: Neil Brown <neilb@xxxxxxxxxxxxxxx>

----------- Diffstat output ------------
./fs/dcache.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)

diff ./fs/dcache.c~current~ ./fs/dcache.c
--- ./fs/dcache.c~current~ 2004-05-28 14:20:00.000000000 +1000
+++ ./fs/dcache.c 2004-05-28 14:20:16.000000000 +1000
@@ -259,7 +259,7 @@ int d_invalidate(struct dentry * dentry)
static inline struct dentry * __dget_locked(struct dentry *dentry)
{
atomic_inc(&dentry->d_count);
- if (atomic_read(&dentry->d_count) == 1) {
+ if (!list_empty(&dentry->d_lru)) {
dentry_stat.nr_unused--;
list_del_init(&dentry->d_lru);
}
@@ -935,8 +935,9 @@ struct dentry *d_splice_alias(struct ino
* lookup is going on.
*
* dentry_unused list is not updated even if lookup finds the required dentry
- * in there. It is updated in places such as prune_dcache, shrink_dcache_sb and
- * select_parent. This laziness saves lookup from dcache_lock acquisition.
+ * in there. It is updated in places such as prune_dcache, shrink_dcache_sb,
+ * select_parent and __dget_locked. This laziness saves lookup from dcache_lock
+ * acquisition.
*
* d_lookup() is protected against the concurrent renames in some unrelated
* directory using the seqlockt_t rename_lock.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/