diff options
author | Nick Piggin <npiggin@kernel.dk> | 2011-01-07 06:49:33 (GMT) |
---|---|---|
committer | Nick Piggin <npiggin@kernel.dk> | 2011-01-07 06:50:21 (GMT) |
commit | da5029563a0a026c64821b09e8e7b4fd81d3fe1b (patch) | |
tree | 5d5618e0cb382390073377b1be7d0aa76879ac54 /fs/autofs4 | |
parent | b7ab39f631f505edc2bbdb86620d5493f995c9da (diff) | |
download | linux-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')
-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 3d283ab..3912dcf 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 413b564..ee64020 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); |