aboutsummaryrefslogtreecommitdiffstats
path: root/fs/autofs4
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2014-10-13 18:52:22 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-13 20:18:16 -0400
commitef16cc5909c907586f4eba5455e183fd319637c8 (patch)
tree8c85bca785379b19f215b210a89717e7cd51c4c8 /fs/autofs4
parent4d885f90e3784df77945101d8ec32dc798a49862 (diff)
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: NeilBrown <neilb@suse.de> Reviewed-by: Ian Kent <raven@themaw.net> Tested-by: Ian Kent <raven@themaw.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/autofs4')
-rw-r--r--fs/autofs4/root.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 2296c8301b66..d76d083f2f06 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -433,8 +433,6 @@ static int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
433 433
434 /* The daemon never waits. */ 434 /* The daemon never waits. */
435 if (autofs4_oz_mode(sbi)) { 435 if (autofs4_oz_mode(sbi)) {
436 if (rcu_walk)
437 return 0;
438 if (!d_mountpoint(dentry)) 436 if (!d_mountpoint(dentry))
439 return -EISDIR; 437 return -EISDIR;
440 return 0; 438 return 0;
@@ -452,12 +450,28 @@ static int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
452 if (status) 450 if (status)
453 return status; 451 return status;
454 452
455 if (rcu_walk) 453 if (rcu_walk) {
456 /* it is always safe to return 0 as the worst that 454 /* We don't need fs_lock in rcu_walk mode,
457 * will happen is we retry in REF-walk mode. 455 * just testing 'AUTOFS_INFO_NO_RCU' is enough.
458 * Better than always taking a lock. 456 * simple_empty() takes a spinlock, so leave it
457 * to last.
458 * We only return -EISDIR when certain this isn't
459 * a mount-trap.
459 */ 460 */
461 struct inode *inode;
462 if (ino->flags & (AUTOFS_INF_EXPIRING | AUTOFS_INF_NO_RCU))
463 return 0;
464 if (d_mountpoint(dentry))
465 return 0;
466 inode = ACCESS_ONCE(dentry->d_inode);
467 if (inode && S_ISLNK(inode->i_mode))
468 return -EISDIR;
469 if (list_empty(&dentry->d_subdirs))
470 return 0;
471 if (!simple_empty(dentry))
472 return -EISDIR;
460 return 0; 473 return 0;
474 }
461 475
462 spin_lock(&sbi->fs_lock); 476 spin_lock(&sbi->fs_lock);
463 /* 477 /*