diff options
author | Nick Piggin <npiggin@kernel.dk> | 2011-01-07 01:49:33 -0500 |
---|---|---|
committer | Nick Piggin <npiggin@kernel.dk> | 2011-01-07 01:50:21 -0500 |
commit | da5029563a0a026c64821b09e8e7b4fd81d3fe1b (patch) | |
tree | 5d5618e0cb382390073377b1be7d0aa76879ac54 /fs/autofs4 | |
parent | b7ab39f631f505edc2bbdb86620d5493f995c9da (diff) |
fs: dcache scale d_unhashed
Protect d_unhashed(dentry) condition with d_lock. This means keeping
DCACHE_UNHASHED bit in synch with hash manipulations.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Diffstat (limited to 'fs/autofs4')
-rw-r--r-- | fs/autofs4/autofs_i.h | 13 | ||||
-rw-r--r-- | fs/autofs4/expire.c | 21 |
2 files changed, 16 insertions, 18 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index 3d283abf67d7..3912dcf047e5 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h | |||
@@ -254,19 +254,6 @@ static inline int simple_positive(struct dentry *dentry) | |||
254 | return dentry->d_inode && !d_unhashed(dentry); | 254 | return dentry->d_inode && !d_unhashed(dentry); |
255 | } | 255 | } |
256 | 256 | ||
257 | static inline int __simple_empty(struct dentry *dentry) | ||
258 | { | ||
259 | struct dentry *child; | ||
260 | int ret = 0; | ||
261 | |||
262 | list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child) | ||
263 | if (simple_positive(child)) | ||
264 | goto out; | ||
265 | ret = 1; | ||
266 | out: | ||
267 | return ret; | ||
268 | } | ||
269 | |||
270 | static inline void autofs4_add_expiring(struct dentry *dentry) | 257 | static inline void autofs4_add_expiring(struct dentry *dentry) |
271 | { | 258 | { |
272 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | 259 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); |
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index 413b5642e6cf..ee6402050f13 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c | |||
@@ -160,14 +160,18 @@ static int autofs4_tree_busy(struct vfsmount *mnt, | |||
160 | 160 | ||
161 | spin_lock(&dcache_lock); | 161 | spin_lock(&dcache_lock); |
162 | for (p = top; p; p = next_dentry(p, top)) { | 162 | for (p = top; p; p = next_dentry(p, top)) { |
163 | spin_lock(&p->d_lock); | ||
163 | /* Negative dentry - give up */ | 164 | /* Negative dentry - give up */ |
164 | if (!simple_positive(p)) | 165 | if (!simple_positive(p)) { |
166 | spin_unlock(&p->d_lock); | ||
165 | continue; | 167 | continue; |
168 | } | ||
166 | 169 | ||
167 | DPRINTK("dentry %p %.*s", | 170 | DPRINTK("dentry %p %.*s", |
168 | p, (int) p->d_name.len, p->d_name.name); | 171 | p, (int) p->d_name.len, p->d_name.name); |
169 | 172 | ||
170 | p = dget(p); | 173 | p = dget_dlock(p); |
174 | spin_unlock(&p->d_lock); | ||
171 | spin_unlock(&dcache_lock); | 175 | spin_unlock(&dcache_lock); |
172 | 176 | ||
173 | /* | 177 | /* |
@@ -228,14 +232,18 @@ static struct dentry *autofs4_check_leaves(struct vfsmount *mnt, | |||
228 | 232 | ||
229 | spin_lock(&dcache_lock); | 233 | spin_lock(&dcache_lock); |
230 | for (p = parent; p; p = next_dentry(p, parent)) { | 234 | for (p = parent; p; p = next_dentry(p, parent)) { |
235 | spin_lock(&p->d_lock); | ||
231 | /* Negative dentry - give up */ | 236 | /* Negative dentry - give up */ |
232 | if (!simple_positive(p)) | 237 | if (!simple_positive(p)) { |
238 | spin_unlock(&p->d_lock); | ||
233 | continue; | 239 | continue; |
240 | } | ||
234 | 241 | ||
235 | DPRINTK("dentry %p %.*s", | 242 | DPRINTK("dentry %p %.*s", |
236 | p, (int) p->d_name.len, p->d_name.name); | 243 | p, (int) p->d_name.len, p->d_name.name); |
237 | 244 | ||
238 | p = dget(p); | 245 | p = dget_dlock(p); |
246 | spin_unlock(&p->d_lock); | ||
239 | spin_unlock(&dcache_lock); | 247 | spin_unlock(&dcache_lock); |
240 | 248 | ||
241 | if (d_mountpoint(p)) { | 249 | if (d_mountpoint(p)) { |
@@ -324,12 +332,15 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, | |||
324 | struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child); | 332 | struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child); |
325 | 333 | ||
326 | /* Negative dentry - give up */ | 334 | /* Negative dentry - give up */ |
335 | spin_lock(&dentry->d_lock); | ||
327 | if (!simple_positive(dentry)) { | 336 | if (!simple_positive(dentry)) { |
328 | next = next->next; | 337 | next = next->next; |
338 | spin_unlock(&dentry->d_lock); | ||
329 | continue; | 339 | continue; |
330 | } | 340 | } |
331 | 341 | ||
332 | dentry = dget(dentry); | 342 | dentry = dget_dlock(dentry); |
343 | spin_unlock(&dentry->d_lock); | ||
333 | spin_unlock(&dcache_lock); | 344 | spin_unlock(&dcache_lock); |
334 | 345 | ||
335 | spin_lock(&sbi->fs_lock); | 346 | spin_lock(&sbi->fs_lock); |