summaryrefslogtreecommitdiff
path: root/fs/autofs4/expire.c
diff options
context:
space:
mode:
authorNick Piggin <npiggin@kernel.dk>2011-01-07 09:49:33 +0300
committerNick Piggin <npiggin@kernel.dk>2011-01-07 09:50:21 +0300
commitda5029563a0a026c64821b09e8e7b4fd81d3fe1b (patch)
tree5d5618e0cb382390073377b1be7d0aa76879ac54 /fs/autofs4/expire.c
parentb7ab39f631f505edc2bbdb86620d5493f995c9da (diff)
downloadlinux-da5029563a0a026c64821b09e8e7b4fd81d3fe1b.tar.xz
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/expire.c')
-rw-r--r--fs/autofs4/expire.c21
1 files changed, 16 insertions, 5 deletions
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,
spin_lock(&dcache_lock);
for (p = top; p; p = next_dentry(p, top)) {
+ spin_lock(&p->d_lock);
/* Negative dentry - give up */
- if (!simple_positive(p))
+ if (!simple_positive(p)) {
+ spin_unlock(&p->d_lock);
continue;
+ }
DPRINTK("dentry %p %.*s",
p, (int) p->d_name.len, p->d_name.name);
- p = dget(p);
+ p = dget_dlock(p);
+ spin_unlock(&p->d_lock);
spin_unlock(&dcache_lock);
/*
@@ -228,14 +232,18 @@ static struct dentry *autofs4_check_leaves(struct vfsmount *mnt,
spin_lock(&dcache_lock);
for (p = parent; p; p = next_dentry(p, parent)) {
+ spin_lock(&p->d_lock);
/* Negative dentry - give up */
- if (!simple_positive(p))
+ if (!simple_positive(p)) {
+ spin_unlock(&p->d_lock);
continue;
+ }
DPRINTK("dentry %p %.*s",
p, (int) p->d_name.len, p->d_name.name);
- p = dget(p);
+ p = dget_dlock(p);
+ spin_unlock(&p->d_lock);
spin_unlock(&dcache_lock);
if (d_mountpoint(p)) {
@@ -324,12 +332,15 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
/* Negative dentry - give up */
+ spin_lock(&dentry->d_lock);
if (!simple_positive(dentry)) {
next = next->next;
+ spin_unlock(&dentry->d_lock);
continue;
}
- dentry = dget(dentry);
+ dentry = dget_dlock(dentry);
+ spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
spin_lock(&sbi->fs_lock);