Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

NeilBrown and committed by
Linus Torvalds
ef16cc59 4d885f90

+20 -6
+20 -6
fs/autofs4/root.c
··· 433 433 434 434 /* The daemon never waits. */ 435 435 if (autofs4_oz_mode(sbi)) { 436 - if (rcu_walk) 437 - return 0; 438 436 if (!d_mountpoint(dentry)) 439 437 return -EISDIR; 440 438 return 0; ··· 450 452 if (status) 451 453 return status; 452 454 453 - if (rcu_walk) 454 - /* it is always safe to return 0 as the worst that 455 - * will happen is we retry in REF-walk mode. 456 - * Better than always taking a lock. 455 + if (rcu_walk) { 456 + /* We don't need fs_lock in rcu_walk mode, 457 + * just testing 'AUTOFS_INFO_NO_RCU' is enough. 458 + * simple_empty() takes a spinlock, so leave it 459 + * to last. 460 + * We only return -EISDIR when certain this isn't 461 + * a mount-trap. 457 462 */ 463 + struct inode *inode; 464 + if (ino->flags & (AUTOFS_INF_EXPIRING | AUTOFS_INF_NO_RCU)) 465 + return 0; 466 + if (d_mountpoint(dentry)) 467 + return 0; 468 + inode = ACCESS_ONCE(dentry->d_inode); 469 + if (inode && S_ISLNK(inode->i_mode)) 470 + return -EISDIR; 471 + if (list_empty(&dentry->d_subdirs)) 472 + return 0; 473 + if (!simple_empty(dentry)) 474 + return -EISDIR; 458 475 return 0; 476 + } 459 477 460 478 spin_lock(&sbi->fs_lock); 461 479 /*