diff options
author | Nick Piggin <npiggin@suse.de> | 2010-01-29 15:38:22 -0800 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2010-04-27 17:32:33 +0200 |
commit | b9ab2f38fdee96ff49b8a7bbb65cbfc60921e40c (patch) | |
tree | e5e785ba4ae7ec89564914c50638a22d756b6d19 /security | |
parent | d4fe09131b66c5a7176a5dbfc9bd1ef6939643e8 (diff) | |
download | lwn-b9ab2f38fdee96ff49b8a7bbb65cbfc60921e40c.tar.gz lwn-b9ab2f38fdee96ff49b8a7bbb65cbfc60921e40c.zip |
fs-dcache-scale-d_subdirs
Protect d_subdirs and d_child with d_lock, except in filesystems that aren't
using dcache_lock for these anyway (eg. using i_mutex).
XXX: probably don't need parent lock in inotify (because child lock
should stabilize parent). Also, possibly some filesystems don't need so
much locking (eg. of child dentry when modifying d_child, so long as
parent is locked)... but be on the safe side. Hmm, maybe we should just
say d_child list is protected by d_parent->d_lock. d_parent could remain
protected with d_lock.
Signed-off-by: Nick Piggin <npiggin@suse.de>
Signed-off-by: John Stultz <johnstul@us.ibm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'security')
-rw-r--r-- | security/selinux/selinuxfs.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index fab36fdf2769..dec4344462f9 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -944,22 +944,30 @@ static void sel_remove_entries(struct dentry *de) struct list_head *node; spin_lock(&dcache_lock); + spin_lock(&de->d_lock); node = de->d_subdirs.next; while (node != &de->d_subdirs) { struct dentry *d = list_entry(node, struct dentry, d_u.d_child); + + spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED); list_del_init(node); if (d->d_inode) { - d = dget_locked(d); + dget_locked_dlock(d); + spin_unlock(&de->d_lock); + spin_unlock(&d->d_lock); spin_unlock(&dcache_lock); d_delete(d); simple_unlink(de->d_inode, d); dput(d); spin_lock(&dcache_lock); - } + spin_lock(&de->d_lock); + } else + spin_unlock(&d->d_lock); node = de->d_subdirs.next; } + spin_unlock(&de->d_lock); spin_unlock(&dcache_lock); } |