2003-06-19 12:55:06

by Maneesh Soni

[permalink] [raw]
Subject: [patch 0/3] 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

--
Maneesh Soni
IBM Linux Technology Center,
IBM India Software Lab, Bangalore.
Phone: +91-80-5044999 email: [email protected]
http://lse.sourceforge.net/


2003-06-19 12:56:32

by Maneesh Soni

[permalink] [raw]
Subject: [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(+)

diff -puN fs/nfs/dir.c~nfs_unlink-d_count-fix fs/nfs/dir.c
--- linux-2.5.72-mm2/fs/nfs/dir.c~nfs_unlink-d_count-fix 2003-06-19 17:38:51.000000000 +0530
+++ linux-2.5.72-mm2-maneesh/fs/nfs/dir.c 2003-06-19 17:38:56.000000000 +0530
@@ -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)

_
--
Maneesh Soni
IBM Linux Technology Center,
IBM India Software Lab, Bangalore.
Phone: +91-80-5044999 email: [email protected]
http://lse.sourceforge.net/

2003-06-19 12:55:35

by Maneesh Soni

[permalink] [raw]
Subject: [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(+)

diff -puN fs/dcache.c~d_invalidate-fix fs/dcache.c
--- linux-2.5.72-mm2/fs/dcache.c~d_invalidate-fix 2003-06-19 17:34:38.000000000 +0530
+++ linux-2.5.72-mm2-maneesh/fs/dcache.c 2003-06-19 17:35:14.000000000 +0530
@@ -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;
}

_
--
Maneesh Soni
IBM Linux Technology Center,
IBM India Software Lab, Bangalore.
Phone: +91-80-5044999 email: [email protected]
http://lse.sourceforge.net/

2003-06-19 12:57:35

by Maneesh Soni

[permalink] [raw]
Subject: [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(+)

diff -puN fs/hpfs/namei.c~hpfs-d_count-fix fs/hpfs/namei.c
--- linux-2.5.72-mm2/fs/hpfs/namei.c~hpfs-d_count-fix 2003-06-19 17:46:05.000000000 +0530
+++ linux-2.5.72-mm2-maneesh/fs/hpfs/namei.c 2003-06-19 17:46:19.000000000 +0530
@@ -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;

_
--
Maneesh Soni
IBM Linux Technology Center,
IBM India Software Lab, Bangalore.
Phone: +91-80-5044999 email: [email protected]
http://lse.sourceforge.net/