]> git.hungrycats.org Git - linux/commitdiff
[PATCH] fs/dcache.c: avoid race when updating nr_unused count of unused dentries.
authorAndrew Morton <akpm@osdl.org>
Sat, 29 May 2004 03:58:56 +0000 (20:58 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Sat, 29 May 2004 03:58:56 +0000 (20:58 -0700)
From: NeilBrown <neilb@cse.unsw.edu.au>

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.

Cc: Maneesh Soni <maneesh@in.ibm.com>, Dipankar Sarma <dipankar@in.ibm.com>
From: Greg Banks <gnb@melbourne.sgi.com>
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/dcache.c

index 5f6e53022ce1c3744d7d18536b27e9bd93545aef..613ff66dacde2d1b7ed339da5b3b1fa46b59b871 100644 (file)
@@ -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 inode *inode, struct dentry *dentry)
  * 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.