dentry->d_count fixes
Subsystems (3)
cover dentry->d_count fixes
Hi,
There are few races regarding the use of dentry->d_count at various places as pointed by Trond. I have audited these and made following patches for the places which I think are problemetic.
1. d_invalidate-fix.patch
- fixes race between d_invalidate & lockless d_lookup
2. nfs_unlink-d_count-fix.patch
- fixes race with nfs_unlink()
3. hpfs-d_count-fix.patch
- fixes race with hpfs_unlink()
Thanks,
Maneesh
Signature · 5 lines
Maneesh Soni IBM Linux Technology Center, IBM India Software Lab, Bangalore. Phone: +91-80-5044999 email: [email protected] http://lse.sourceforge.net/
PATCH 1/3 dentry->d_count fixes
- d_invalidate() can incorrectly return success instead of returning -EBUSY as we can have situations where lockless d_lookup has found a dentry successfully before d_invalidate drops it
fs/dcache.c | 3 +++ 1 files changed, 3 insertions(+)
fs/dcache.c renamed from fs/dcache.c~d_invalidate-fix +3 -0
@@ -232,14 +232,17 @@ int d_invalidate(struct dentry * dentry)* we might still populate it if it was a * working directory or similar). */ +spin_lock (&dentry->d_lock);if (atomic_read (&dentry->d_count) >1 ) {if (dentry->d_inode &&S_ISDIR (dentry->d_inode->i_mode)) { +spin_unlock (&dentry->d_lock);spin_unlock (&dcache_lock);return -EBUSY ; } }__d_drop (dentry); +spin_unlock (&dentry->d_lock);spin_unlock (&dcache_lock);return 0 ; }
_
Signature · 5 lines
Maneesh Soni IBM Linux Technology Center, IBM India Software Lab, Bangalore. Phone: +91-80-5044999 email: [email protected] http://lse.sourceforge.net/
PATCH 2/3 dentry->d_count fixes
- 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(+)
fs/nfs/dir.c renamed from fs/nfs/dir.c~nfs_unlink-d_count-fix +3 -0
@@ -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)
_
Signature · 5 lines
Maneesh Soni IBM Linux Technology Center, IBM India Software Lab, Bangalore. Phone: +91-80-5044999 email: [email protected] http://lse.sourceforge.net/
PATCH 3/3 dentry->d_count fixes
- hpfs_unlink() can race with lockless d_lookup(), as we can have situations where d_lookup() has successfully looked-up a dentry and at the sametime hpfs_unlink()--->d_drop() has dropped it. Taking the per dentry lock before checking the d_count in hpfs_unlink() solves this race condition.
fs/hpfs/namei.c | 3 +++ 1 files changed, 3 insertions(+)
fs/hpfs/namei.c renamed from fs/hpfs/namei.c~hpfs-d_count-fix +3 -0
@@ -372,12 +372,15 @@ again:if (rep) goto ret;d_drop (dentry); +spin_lock (&dentry->d_lock);if (atomic_read (&dentry->d_count) >1 ||permission (inode,MAY_WRITE ) ||get_write_access (inode)) { +spin_unlock (&dentry->d_lock);d_rehash (dentry); goto ret; } +spin_unlock (&dentry->d_lock);/*printk("HPFS: truncating file before delete.\n");*/ newattrs.ia_size =0 ; newattrs.ia_valid =ATTR_SIZE |ATTR_CTIME ;
_
Signature · 5 lines
Maneesh Soni IBM Linux Technology Center, IBM India Software Lab, Bangalore. Phone: +91-80-5044999 email: [email protected] http://lse.sourceforge.net/