From: Maneesh Soni <maneesh@in.ibm.com>

- nfs_unlink() can race with lockless d_lookup() as d_lookup() can
  successfully lookup a dentry for which nfs_unlink() can assume that no one
  else is using and can go ahead and do nfs_safe_remove() on it. By using
  per dentry lock, it is solved as we d_lookup() will fail the lookup for
  unhashed dentries.




 fs/nfs/dir.c |    3 +++
 1 files changed, 3 insertions(+)

diff -puN fs/nfs/dir.c~nfs_unlink-d_count-fix fs/nfs/dir.c
--- 25/fs/nfs/dir.c~nfs_unlink-d_count-fix	2003-06-19 09:53:20.000000000 -0700
+++ 25-akpm/fs/nfs/dir.c	2003-06-19 09:53:20.000000000 -0700
@@ -1015,7 +1015,9 @@ static int nfs_unlink(struct inode *dir,
 
 	lock_kernel();
 	spin_lock(&dcache_lock);
+	spin_lock(&dentry->d_lock);
 	if (atomic_read(&dentry->d_count) > 1) {
+		spin_unlock(&dentry->d_lock);
 		spin_unlock(&dcache_lock);
 		error = nfs_sillyrename(dir, dentry);
 		unlock_kernel();
@@ -1025,6 +1027,7 @@ static int nfs_unlink(struct inode *dir,
 		__d_drop(dentry);
 		need_rehash = 1;
 	}
+	spin_unlock(&dentry->d_lock);
 	spin_unlock(&dcache_lock);
 	error = nfs_safe_remove(dentry);
 	if (!error)

_