Commit fd889c1d authored by Ian Kent's avatar Ian Kent Committed by james toy

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: default avatarIan 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: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 11e7a9ed
...@@ -97,6 +97,7 @@ struct autofs_info { ...@@ -97,6 +97,7 @@ struct autofs_info {
#define AUTOFS_INF_EXPIRING (1<<0) /* dentry is in the process of expiring */ #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_MOUNTPOINT (1<<1) /* mountpoint status for direct expire */
#define AUTOFS_INF_PENDING (1<<2) /* dentry pending mount */
struct autofs_wait_queue { struct autofs_wait_queue {
wait_queue_head_t queue; wait_queue_head_t queue;
...@@ -163,7 +164,7 @@ static inline int autofs4_ispending(struct dentry *dentry) ...@@ -163,7 +164,7 @@ static inline int autofs4_ispending(struct dentry *dentry)
{ {
struct autofs_info *inf = autofs4_dentry_ino(dentry); struct autofs_info *inf = autofs4_dentry_ino(dentry);
if (dentry->d_flags & DCACHE_AUTOFS_PENDING) if (inf->flags & AUTOFS_INF_PENDING)
return 1; return 1;
if (inf->flags & AUTOFS_INF_EXPIRING) if (inf->flags & AUTOFS_INF_EXPIRING)
......
...@@ -27,7 +27,7 @@ static inline int autofs4_can_expire(struct dentry *dentry, ...@@ -27,7 +27,7 @@ static inline int autofs4_can_expire(struct dentry *dentry,
return 0; return 0;
/* No point expiring a pending mount */ /* No point expiring a pending mount */
if (dentry->d_flags & DCACHE_AUTOFS_PENDING) if (ino->flags & AUTOFS_INF_PENDING)
return 0; return 0;
if (!do_now) { if (!do_now) {
......
...@@ -166,32 +166,32 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags) ...@@ -166,32 +166,32 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags)
/* Turn this into a real negative dentry? */ /* Turn this into a real negative dentry? */
if (status == -ENOENT) { if (status == -ENOENT) {
spin_lock(&dentry->d_lock); spin_lock(&sbi->fs_lock);
dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; ino->flags &= ~AUTOFS_INF_PENDING;
spin_unlock(&dentry->d_lock); spin_unlock(&sbi->fs_lock);
return status; return status;
} else if (status) { } else if (status) {
/* Return a negative dentry, but leave it "pending" */ /* Return a negative dentry, but leave it "pending" */
return status; return status;
} }
/* Trigger mount for path component or follow link */ /* 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) || autofs4_need_mount(flags) ||
current->link_count) { current->link_count) {
DPRINTK("waiting for mount name=%.*s", DPRINTK("waiting for mount name=%.*s",
dentry->d_name.len, dentry->d_name.name); dentry->d_name.len, dentry->d_name.name);
spin_lock(&dentry->d_lock); spin_lock(&sbi->fs_lock);
dentry->d_flags |= DCACHE_AUTOFS_PENDING; ino->flags |= AUTOFS_INF_PENDING;
spin_unlock(&dentry->d_lock); spin_unlock(&sbi->fs_lock);
status = autofs4_wait(sbi, dentry, NFY_MOUNT); status = autofs4_wait(sbi, dentry, NFY_MOUNT);
DPRINTK("mount done status=%d", status); DPRINTK("mount done status=%d", status);
if (status) { if (status) {
spin_lock(&dentry->d_lock); spin_lock(&sbi->fs_lock);
dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; ino->flags &= ~AUTOFS_INF_PENDING;
spin_unlock(&dentry->d_lock); spin_unlock(&sbi->fs_lock);
return status; return status;
} }
} }
...@@ -200,9 +200,9 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags) ...@@ -200,9 +200,9 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags)
if (ino) if (ino)
ino->last_used = jiffies; ino->last_used = jiffies;
spin_lock(&dentry->d_lock); spin_lock(&sbi->fs_lock);
dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; ino->flags &= ~AUTOFS_INF_PENDING;
spin_unlock(&dentry->d_lock); spin_unlock(&sbi->fs_lock);
return 0; return 0;
} }
...@@ -243,18 +243,23 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) ...@@ -243,18 +243,23 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
/* We trigger a mount for almost all flags */ /* We trigger a mount for almost all flags */
lookup_type = autofs4_need_mount(nd->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; goto follow;
}
/* /*
* If the dentry contains directories then it is an autofs * If the dentry contains directories then it is an autofs
* multi-mount with no root mount offset. So don't try to * multi-mount with no root mount offset. So don't try to
* mount it again. * mount it again.
*/ */
spin_lock(&dcache_lock); if (ino->flags & AUTOFS_INF_PENDING ||
if (dentry->d_flags & DCACHE_AUTOFS_PENDING ||
(!d_mountpoint(dentry) && __simple_empty(dentry))) { (!d_mountpoint(dentry) && __simple_empty(dentry))) {
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
spin_unlock(&sbi->fs_lock);
status = try_to_fill_dentry(dentry, 0); status = try_to_fill_dentry(dentry, 0);
if (status) if (status)
...@@ -263,6 +268,7 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) ...@@ -263,6 +268,7 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
goto follow; goto follow;
} }
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
spin_unlock(&sbi->fs_lock);
follow: follow:
/* /*
* If there is no root mount it must be an autofs * If there is no root mount it must be an autofs
...@@ -525,9 +531,10 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s ...@@ -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); current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode);
unhashed = autofs4_lookup_active(sbi, dentry->d_parent, &dentry->d_name); unhashed = autofs4_lookup_active(sbi, dentry->d_parent, &dentry->d_name);
if (unhashed) if (unhashed) {
dentry = unhashed; dentry = unhashed;
else { ino = autofs4_dentry_ino(dentry);
} else {
/* /*
* Mark the dentry incomplete but don't hash it. We do this * Mark the dentry incomplete but don't hash it. We do this
* to serialize our inode creation operations (symlink and * to serialize our inode creation operations (symlink and
...@@ -569,15 +576,14 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s ...@@ -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 * be quite complete but the directory has been removed
* so it must have been successful, so just wait for it. * so it must have been successful, so just wait for it.
*/ */
ino = autofs4_dentry_ino(expiring);
autofs4_expire_wait(expiring); autofs4_expire_wait(expiring);
autofs4_del_expiring(expiring); autofs4_del_expiring(expiring);
dput(expiring); dput(expiring);
} }
spin_lock(&dentry->d_lock); spin_lock(&sbi->fs_lock);
dentry->d_flags |= DCACHE_AUTOFS_PENDING; ino->flags |= AUTOFS_INF_PENDING;
spin_unlock(&dentry->d_lock); spin_unlock(&sbi->fs_lock);
if (dentry->d_op && dentry->d_op->d_revalidate) if (dentry->d_op && dentry->d_op->d_revalidate)
(dentry->d_op->d_revalidate)(dentry, nd); (dentry->d_op->d_revalidate)(dentry, nd);
mutex_lock(&dir->i_mutex); mutex_lock(&dir->i_mutex);
...@@ -587,7 +593,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s ...@@ -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 * If we are still pending, check if we had to handle
* a signal. If so we can force a restart.. * 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 */ /* See if we were interrupted */
if (signal_pending(current)) { if (signal_pending(current)) {
sigset_t *sigset = &current->pending.signal; sigset_t *sigset = &current->pending.signal;
...@@ -600,9 +606,9 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s ...@@ -600,9 +606,9 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
} }
} }
if (!oz_mode) { if (!oz_mode) {
spin_lock(&dentry->d_lock); spin_lock(&sbi->fs_lock);
dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; ino->flags &= ~AUTOFS_INF_PENDING;
spin_unlock(&dentry->d_lock); spin_unlock(&sbi->fs_lock);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment