aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorNick Piggin <npiggin@kernel.dk>2011-01-07 01:49:34 -0500
committerNick Piggin <npiggin@kernel.dk>2011-01-07 01:50:21 -0500
commit2fd6b7f50797f2e993eea59e0a0b8c6399c811dc (patch)
treece33b94b34844c09103836cf4cfa4364b742f217 /security
parentda5029563a0a026c64821b09e8e7b4fd81d3fe1b (diff)
fs: dcache scale 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). Note: if we change the locking rule in future so that ->d_child protection is provided only with ->d_parent->d_lock, it may allow us to reduce some locking. But it would be an exception to an otherwise regular locking scheme, so we'd have to see some good results. Probably not worthwhile. Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Diffstat (limited to 'security')
-rw-r--r--security/selinux/selinuxfs.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 073fd5b0a53a..017ec096446e 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -1146,22 +1146,30 @@ static void sel_remove_entries(struct dentry *de)
1146 struct list_head *node; 1146 struct list_head *node;
1147 1147
1148 spin_lock(&dcache_lock); 1148 spin_lock(&dcache_lock);
1149 spin_lock(&de->d_lock);
1149 node = de->d_subdirs.next; 1150 node = de->d_subdirs.next;
1150 while (node != &de->d_subdirs) { 1151 while (node != &de->d_subdirs) {
1151 struct dentry *d = list_entry(node, struct dentry, d_u.d_child); 1152 struct dentry *d = list_entry(node, struct dentry, d_u.d_child);
1153
1154 spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
1152 list_del_init(node); 1155 list_del_init(node);
1153 1156
1154 if (d->d_inode) { 1157 if (d->d_inode) {
1155 d = dget_locked(d); 1158 dget_locked_dlock(d);
1159 spin_unlock(&de->d_lock);
1160 spin_unlock(&d->d_lock);
1156 spin_unlock(&dcache_lock); 1161 spin_unlock(&dcache_lock);
1157 d_delete(d); 1162 d_delete(d);
1158 simple_unlink(de->d_inode, d); 1163 simple_unlink(de->d_inode, d);
1159 dput(d); 1164 dput(d);
1160 spin_lock(&dcache_lock); 1165 spin_lock(&dcache_lock);
1161 } 1166 spin_lock(&de->d_lock);
1167 } else
1168 spin_unlock(&d->d_lock);
1162 node = de->d_subdirs.next; 1169 node = de->d_subdirs.next;
1163 } 1170 }
1164 1171
1172 spin_unlock(&de->d_lock);
1165 spin_unlock(&dcache_lock); 1173 spin_unlock(&dcache_lock);
1166} 1174}
1167 1175