Commit ef16cc59 authored by NeilBrown's avatar NeilBrown Committed by Linus Torvalds

autofs4: d_manage() should return -EISDIR when appropriate in rcu-walk mode.

If rcu-walk mode we don't *have* to return -EISDIR for non-mount-traps
as we will simply drop into REF-walk and handling DCACHE_NEED_AUTOMOUNT
dentrys the slow way.  But it is better if we do when possible.

In 'oz_mode', use the same condition as ref-walk: if not a mountpoint,
then it must be -EISDIR.

In regular mode there are most tests needed.  Most of them can be
performed without taking any spinlocks.  If we find a directory that
isn't obviously empty, and isn't mounted on, we need to call
'simple_empty()' which does take a spinlock.  If this turned out to hurt
performance, some other approach could be found to signal when a
directory is known to be empty.
Signed-off-by: default avatarNeilBrown <neilb@suse.de>
Reviewed-by: default avatarIan Kent <raven@themaw.net>
Tested-by: default avatarIan Kent <raven@themaw.net>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 4d885f90
...@@ -433,8 +433,6 @@ static int autofs4_d_manage(struct dentry *dentry, bool rcu_walk) ...@@ -433,8 +433,6 @@ static int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
/* The daemon never waits. */ /* The daemon never waits. */
if (autofs4_oz_mode(sbi)) { if (autofs4_oz_mode(sbi)) {
if (rcu_walk)
return 0;
if (!d_mountpoint(dentry)) if (!d_mountpoint(dentry))
return -EISDIR; return -EISDIR;
return 0; return 0;
...@@ -452,12 +450,28 @@ static int autofs4_d_manage(struct dentry *dentry, bool rcu_walk) ...@@ -452,12 +450,28 @@ static int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
if (status) if (status)
return status; return status;
if (rcu_walk) if (rcu_walk) {
/* it is always safe to return 0 as the worst that /* We don't need fs_lock in rcu_walk mode,
* will happen is we retry in REF-walk mode. * just testing 'AUTOFS_INFO_NO_RCU' is enough.
* Better than always taking a lock. * simple_empty() takes a spinlock, so leave it
* to last.
* We only return -EISDIR when certain this isn't
* a mount-trap.
*/ */
struct inode *inode;
if (ino->flags & (AUTOFS_INF_EXPIRING | AUTOFS_INF_NO_RCU))
return 0;
if (d_mountpoint(dentry))
return 0; return 0;
inode = ACCESS_ONCE(dentry->d_inode);
if (inode && S_ISLNK(inode->i_mode))
return -EISDIR;
if (list_empty(&dentry->d_subdirs))
return 0;
if (!simple_empty(dentry))
return -EISDIR;
return 0;
}
spin_lock(&sbi->fs_lock); spin_lock(&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