diff options
author | Nick Piggin <npiggin@suse.de> | 2010-01-29 18:38:22 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2010-04-27 11:32:33 -0400 |
commit | b9ab2f38fdee96ff49b8a7bbb65cbfc60921e40c (patch) | |
tree | e5e785ba4ae7ec89564914c50638a22d756b6d19 /fs/autofs4/inode.c | |
parent | d4fe09131b66c5a7176a5dbfc9bd1ef6939643e8 (diff) |
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 'fs/autofs4/inode.c')
-rw-r--r-- | fs/autofs4/inode.c | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index d0a3de247458..cf6192583b73 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c | |||
@@ -113,6 +113,7 @@ static void autofs4_force_release(struct autofs_sb_info *sbi) | |||
113 | 113 | ||
114 | spin_lock(&dcache_lock); | 114 | spin_lock(&dcache_lock); |
115 | repeat: | 115 | repeat: |
116 | spin_lock(&this_parent->d_lock); | ||
116 | next = this_parent->d_subdirs.next; | 117 | next = this_parent->d_subdirs.next; |
117 | resume: | 118 | resume: |
118 | while (next != &this_parent->d_subdirs) { | 119 | while (next != &this_parent->d_subdirs) { |
@@ -125,11 +126,13 @@ resume: | |||
125 | } | 126 | } |
126 | 127 | ||
127 | if (!list_empty(&dentry->d_subdirs)) { | 128 | if (!list_empty(&dentry->d_subdirs)) { |
129 | spin_unlock(&this_parent->d_lock); | ||
128 | this_parent = dentry; | 130 | this_parent = dentry; |
129 | goto repeat; | 131 | goto repeat; |
130 | } | 132 | } |
131 | 133 | ||
132 | next = next->next; | 134 | next = next->next; |
135 | spin_unlock(&this_parent->d_lock); | ||
133 | spin_unlock(&dcache_lock); | 136 | spin_unlock(&dcache_lock); |
134 | 137 | ||
135 | DPRINTK("dentry %p %.*s", | 138 | DPRINTK("dentry %p %.*s", |
@@ -137,20 +140,24 @@ resume: | |||
137 | 140 | ||
138 | dput(dentry); | 141 | dput(dentry); |
139 | spin_lock(&dcache_lock); | 142 | spin_lock(&dcache_lock); |
143 | spin_lock(&this_parent->d_lock); | ||
140 | } | 144 | } |
141 | 145 | ||
142 | if (this_parent != sbi->sb->s_root) { | 146 | if (this_parent != sbi->sb->s_root) { |
143 | struct dentry *dentry = this_parent; | 147 | struct dentry *dentry = this_parent; |
144 | 148 | ||
145 | next = this_parent->d_u.d_child.next; | 149 | next = this_parent->d_u.d_child.next; |
150 | spin_unlock(&this_parent->d_lock); | ||
146 | this_parent = this_parent->d_parent; | 151 | this_parent = this_parent->d_parent; |
147 | spin_unlock(&dcache_lock); | 152 | spin_unlock(&dcache_lock); |
148 | DPRINTK("parent dentry %p %.*s", | 153 | DPRINTK("parent dentry %p %.*s", |
149 | dentry, (int)dentry->d_name.len, dentry->d_name.name); | 154 | dentry, (int)dentry->d_name.len, dentry->d_name.name); |
150 | dput(dentry); | 155 | dput(dentry); |
151 | spin_lock(&dcache_lock); | 156 | spin_lock(&dcache_lock); |
157 | spin_lock(&this_parent->d_lock); | ||
152 | goto resume; | 158 | goto resume; |
153 | } | 159 | } |
160 | spin_unlock(&this_parent->d_lock); | ||
154 | spin_unlock(&dcache_lock); | 161 | spin_unlock(&dcache_lock); |
155 | } | 162 | } |
156 | 163 | ||