Skip to content

Commit

Permalink
autofs4: use autofs_info for pending flag
Browse files Browse the repository at this point in the history
Eliminate the use of the d_lock spin lock by using the autofs super block
info spin lock.  This reduces the number of spin locks we use by one and
makes the code for the following patch (to redirect ->d_revalidate() to
->lookup()) a little simpler.

Signed-off-by: Ian Kent <raven@themaw.net>
Cc: Sage Weil <sage@newdream.net>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
Cc: Andreas Dilger <adilger@sun.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Yehuda Saheh <yehuda@newdream.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Ian Kent authored and Linus Torvalds committed Dec 16, 2009
1 parent 36b6413 commit aa952eb
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 28 deletions.
3 changes: 2 additions & 1 deletion fs/autofs4/autofs_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ struct autofs_info {

#define AUTOFS_INF_EXPIRING (1<<0) /* dentry is in the process of expiring */
#define AUTOFS_INF_MOUNTPOINT (1<<1) /* mountpoint status for direct expire */
#define AUTOFS_INF_PENDING (1<<2) /* dentry pending mount */

struct autofs_wait_queue {
wait_queue_head_t queue;
Expand Down Expand Up @@ -163,7 +164,7 @@ static inline int autofs4_ispending(struct dentry *dentry)
{
struct autofs_info *inf = autofs4_dentry_ino(dentry);

if (dentry->d_flags & DCACHE_AUTOFS_PENDING)
if (inf->flags & AUTOFS_INF_PENDING)
return 1;

if (inf->flags & AUTOFS_INF_EXPIRING)
Expand Down
2 changes: 1 addition & 1 deletion fs/autofs4/expire.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ static inline int autofs4_can_expire(struct dentry *dentry,
return 0;

/* No point expiring a pending mount */
if (dentry->d_flags & DCACHE_AUTOFS_PENDING)
if (ino->flags & AUTOFS_INF_PENDING)
return 0;

if (!do_now) {
Expand Down
58 changes: 32 additions & 26 deletions fs/autofs4/root.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,32 +166,32 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags)

/* Turn this into a real negative dentry? */
if (status == -ENOENT) {
spin_lock(&dentry->d_lock);
dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
spin_unlock(&dentry->d_lock);
spin_lock(&sbi->fs_lock);
ino->flags &= ~AUTOFS_INF_PENDING;
spin_unlock(&sbi->fs_lock);
return status;
} else if (status) {
/* Return a negative dentry, but leave it "pending" */
return status;
}
/* Trigger mount for path component or follow link */
} else if (dentry->d_flags & DCACHE_AUTOFS_PENDING ||
} else if (ino->flags & AUTOFS_INF_PENDING ||
autofs4_need_mount(flags) ||
current->link_count) {
DPRINTK("waiting for mount name=%.*s",
dentry->d_name.len, dentry->d_name.name);

spin_lock(&dentry->d_lock);
dentry->d_flags |= DCACHE_AUTOFS_PENDING;
spin_unlock(&dentry->d_lock);
spin_lock(&sbi->fs_lock);
ino->flags |= AUTOFS_INF_PENDING;
spin_unlock(&sbi->fs_lock);
status = autofs4_wait(sbi, dentry, NFY_MOUNT);

DPRINTK("mount done status=%d", status);

if (status) {
spin_lock(&dentry->d_lock);
dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
spin_unlock(&dentry->d_lock);
spin_lock(&sbi->fs_lock);
ino->flags &= ~AUTOFS_INF_PENDING;
spin_unlock(&sbi->fs_lock);
return status;
}
}
Expand All @@ -200,9 +200,9 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags)
if (ino)
ino->last_used = jiffies;

spin_lock(&dentry->d_lock);
dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
spin_unlock(&dentry->d_lock);
spin_lock(&sbi->fs_lock);
ino->flags &= ~AUTOFS_INF_PENDING;
spin_unlock(&sbi->fs_lock);

return 0;
}
Expand Down Expand Up @@ -243,18 +243,23 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)

/* We trigger a mount for almost all flags */
lookup_type = autofs4_need_mount(nd->flags);
if (!(lookup_type || dentry->d_flags & DCACHE_AUTOFS_PENDING))
spin_lock(&sbi->fs_lock);
spin_lock(&dcache_lock);
if (!(lookup_type || ino->flags & AUTOFS_INF_PENDING)) {
spin_unlock(&dcache_lock);
spin_unlock(&sbi->fs_lock);
goto follow;
}

/*
* If the dentry contains directories then it is an autofs
* multi-mount with no root mount offset. So don't try to
* mount it again.
*/
spin_lock(&dcache_lock);
if (dentry->d_flags & DCACHE_AUTOFS_PENDING ||
if (ino->flags & AUTOFS_INF_PENDING ||
(!d_mountpoint(dentry) && __simple_empty(dentry))) {
spin_unlock(&dcache_lock);
spin_unlock(&sbi->fs_lock);

status = try_to_fill_dentry(dentry, 0);
if (status)
Expand All @@ -263,6 +268,7 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
goto follow;
}
spin_unlock(&dcache_lock);
spin_unlock(&sbi->fs_lock);
follow:
/*
* If there is no root mount it must be an autofs
Expand Down Expand Up @@ -525,9 +531,10 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode);

unhashed = autofs4_lookup_active(sbi, dentry->d_parent, &dentry->d_name);
if (unhashed)
if (unhashed) {
dentry = unhashed;
else {
ino = autofs4_dentry_ino(dentry);
} else {
/*
* Mark the dentry incomplete but don't hash it. We do this
* to serialize our inode creation operations (symlink and
Expand Down Expand Up @@ -569,15 +576,14 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
* be quite complete but the directory has been removed
* so it must have been successful, so just wait for it.
*/
ino = autofs4_dentry_ino(expiring);
autofs4_expire_wait(expiring);
autofs4_del_expiring(expiring);
dput(expiring);
}

spin_lock(&dentry->d_lock);
dentry->d_flags |= DCACHE_AUTOFS_PENDING;
spin_unlock(&dentry->d_lock);
spin_lock(&sbi->fs_lock);
ino->flags |= AUTOFS_INF_PENDING;
spin_unlock(&sbi->fs_lock);
if (dentry->d_op && dentry->d_op->d_revalidate)
(dentry->d_op->d_revalidate)(dentry, nd);
mutex_lock(&dir->i_mutex);
Expand All @@ -587,7 +593,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
* If we are still pending, check if we had to handle
* a signal. If so we can force a restart..
*/
if (dentry->d_flags & DCACHE_AUTOFS_PENDING) {
if (ino->flags & AUTOFS_INF_PENDING) {
/* See if we were interrupted */
if (signal_pending(current)) {
sigset_t *sigset = &current->pending.signal;
Expand All @@ -600,9 +606,9 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
}
}
if (!oz_mode) {
spin_lock(&dentry->d_lock);
dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
spin_unlock(&dentry->d_lock);
spin_lock(&sbi->fs_lock);
ino->flags &= ~AUTOFS_INF_PENDING;
spin_unlock(&sbi->fs_lock);
}
}

Expand Down

0 comments on commit aa952eb

Please sign in to comment.