From: Maneesh Soni d_delete() calls dentry_iput() after releasing the per dentry lock. This can race with __d_lookup and lead to situation where we can make dentry negative with ref count > 1. The following patch makes dentry_iput() to hold per dentry lock till d_inode is NULL and dentry has been removed from d_alias list. 25-akpm/fs/dcache.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff -puN fs/dcache.c~d_delete-d_lookup-race-fix fs/dcache.c --- 25/fs/dcache.c~d_delete-d_lookup-race-fix Fri Sep 5 08:11:12 2003 +++ 25-akpm/fs/dcache.c Fri Sep 5 08:11:25 2003 @@ -82,7 +82,7 @@ static void d_free(struct dentry *dentry /* * Release the dentry's inode, using the filesystem * d_iput() operation if defined. - * Called with dcache_lock held, drops it. + * Called with dcache_lock and per dentry lock held, drops both. */ static inline void dentry_iput(struct dentry * dentry) { @@ -90,13 +90,16 @@ static inline void dentry_iput(struct de if (inode) { dentry->d_inode = NULL; list_del_init(&dentry->d_alias); + spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); if (dentry->d_op && dentry->d_op->d_iput) dentry->d_op->d_iput(dentry, inode); else iput(inode); - } else + } else { + spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); + } } /* @@ -177,9 +180,8 @@ kill_it: { dentry_stat.nr_unused--; } list_del(&dentry->d_child); - spin_unlock(&dentry->d_lock); dentry_stat.nr_dentry--; /* For d_free, below */ - /* drops the lock, at that point nobody can reach this dentry */ + /*drops the locks, at that point nobody can reach this dentry */ dentry_iput(dentry); parent = dentry->d_parent; d_free(dentry); @@ -341,7 +343,6 @@ static inline void prune_one_dentry(stru __d_drop(dentry); list_del(&dentry->d_child); - spin_unlock(&dentry->d_lock); dentry_stat.nr_dentry--; /* For d_free, below */ dentry_iput(dentry); parent = dentry->d_parent; @@ -1116,7 +1117,6 @@ void d_delete(struct dentry * dentry) spin_lock(&dcache_lock); spin_lock(&dentry->d_lock); if (atomic_read(&dentry->d_count) == 1) { - spin_unlock(&dentry->d_lock); dentry_iput(dentry); return; } _