summaryrefslogtreecommitdiffstats
path: root/fs/autofs4
diff options
context:
space:
mode:
authorNick Piggin <npiggin@kernel.dk>2011-01-07 17:49:33 +1100
committerNick Piggin <npiggin@kernel.dk>2011-01-07 17:50:21 +1100
commitda5029563a0a026c64821b09e8e7b4fd81d3fe1b (patch)
tree5d5618e0cb382390073377b1be7d0aa76879ac54 /fs/autofs4
parentb7ab39f631f505edc2bbdb86620d5493f995c9da (diff)
downloadlinux-stable-da5029563a0a026c64821b09e8e7b4fd81d3fe1b.tar.gz
linux-stable-da5029563a0a026c64821b09e8e7b4fd81d3fe1b.tar.bz2
linux-stable-da5029563a0a026c64821b09e8e7b4fd81d3fe1b.zip
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.h13
-rw-r--r--fs/autofs4/expire.c21
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)
return dentry->d_inode && !d_unhashed(dentry);
}
-static inline int __simple_empty(struct dentry *dentry)
-{
- struct dentry *child;
- int ret = 0;
-
- list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child)
- if (simple_positive(child))
- goto out;
- ret = 1;
-out:
- return ret;
-}
-
static inline void autofs4_add_expiring(struct dentry *dentry)
{
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,
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);