aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cgroup.c
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 /kernel/cgroup.c
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 'kernel/cgroup.c')
-rw-r--r--kernel/cgroup.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index eb7af39350c6..7b4705b51d4a 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -877,23 +877,31 @@ static void cgroup_clear_directory(struct dentry *dentry)
877 877
878 BUG_ON(!mutex_is_locked(&dentry->d_inode->i_mutex)); 878 BUG_ON(!mutex_is_locked(&dentry->d_inode->i_mutex));
879 spin_lock(&dcache_lock); 879 spin_lock(&dcache_lock);
880 spin_lock(&dentry->d_lock);
880 node = dentry->d_subdirs.next; 881 node = dentry->d_subdirs.next;
881 while (node != &dentry->d_subdirs) { 882 while (node != &dentry->d_subdirs) {
882 struct dentry *d = list_entry(node, struct dentry, d_u.d_child); 883 struct dentry *d = list_entry(node, struct dentry, d_u.d_child);
884
885 spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
883 list_del_init(node); 886 list_del_init(node);
884 if (d->d_inode) { 887 if (d->d_inode) {
885 /* This should never be called on a cgroup 888 /* This should never be called on a cgroup
886 * directory with child cgroups */ 889 * directory with child cgroups */
887 BUG_ON(d->d_inode->i_mode & S_IFDIR); 890 BUG_ON(d->d_inode->i_mode & S_IFDIR);
888 d = dget_locked(d); 891 dget_locked_dlock(d);
892 spin_unlock(&d->d_lock);
893 spin_unlock(&dentry->d_lock);
889 spin_unlock(&dcache_lock); 894 spin_unlock(&dcache_lock);
890 d_delete(d); 895 d_delete(d);
891 simple_unlink(dentry->d_inode, d); 896 simple_unlink(dentry->d_inode, d);
892 dput(d); 897 dput(d);
893 spin_lock(&dcache_lock); 898 spin_lock(&dcache_lock);
894 } 899 spin_lock(&dentry->d_lock);
900 } else
901 spin_unlock(&d->d_lock);
895 node = dentry->d_subdirs.next; 902 node = dentry->d_subdirs.next;
896 } 903 }
904 spin_unlock(&dentry->d_lock);
897 spin_unlock(&dcache_lock); 905 spin_unlock(&dcache_lock);
898} 906}
899 907
@@ -902,10 +910,17 @@ static void cgroup_clear_directory(struct dentry *dentry)
902 */ 910 */
903static void cgroup_d_remove_dir(struct dentry *dentry) 911static void cgroup_d_remove_dir(struct dentry *dentry)
904{ 912{
913 struct dentry *parent;
914
905 cgroup_clear_directory(dentry); 915 cgroup_clear_directory(dentry);
906 916
907 spin_lock(&dcache_lock); 917 spin_lock(&dcache_lock);
918 parent = dentry->d_parent;
919 spin_lock(&parent->d_lock);
920 spin_lock(&dentry->d_lock);
908 list_del_init(&dentry->d_u.d_child); 921 list_del_init(&dentry->d_u.d_child);
922 spin_unlock(&dentry->d_lock);
923 spin_unlock(&parent->d_lock);
909 spin_unlock(&dcache_lock); 924 spin_unlock(&dcache_lock);
910 remove_dir(dentry); 925 remove_dir(dentry);
911} 926}