aboutsummaryrefslogtreecommitdiffstats
path: root/fs/autofs4
diff options
context:
space:
mode:
authorIan Kent <raven@themaw.net>2012-12-13 21:23:23 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-13 22:13:25 -0500
commitf55fb0c24386cee8b78f60d60186716bd0909493 (patch)
tree5ca3ab6c4c94c33f99934891c681c280778fb1c8 /fs/autofs4
parent29594404d7fe73cd80eaa4ee8c43dcc53970c60e (diff)
autofs4 - dont clear DCACHE_NEED_AUTOMOUNT on rootless mount
The DCACHE_NEED_AUTOMOUNT flag is cleared on mount and set on expire for autofs rootless multi-mount dentrys to prevent unnecessary calls to ->d_automount(). Since DCACHE_MANAGE_TRANSIT is always set on autofs dentrys ->d_managed() is always called so the check can be done in ->d_manage() without the need to change the flag. This still avoids unnecessary calls to ->d_automount(), adds negligible overhead and eliminates a seriously ugly check in the expire code. Signed-off-by: Ian Kent <raven@themaw.net> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/autofs4')
-rw-r--r--fs/autofs4/expire.c9
-rw-r--r--fs/autofs4/root.c61
2 files changed, 36 insertions, 34 deletions
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 842d00048a65..01443ce43ee7 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -548,15 +548,6 @@ int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
548 548
549 spin_lock(&sbi->fs_lock); 549 spin_lock(&sbi->fs_lock);
550 ino->flags &= ~AUTOFS_INF_EXPIRING; 550 ino->flags &= ~AUTOFS_INF_EXPIRING;
551 spin_lock(&dentry->d_lock);
552 if (!ret) {
553 if ((IS_ROOT(dentry) ||
554 (autofs_type_indirect(sbi->type) &&
555 IS_ROOT(dentry->d_parent))) &&
556 !(dentry->d_flags & DCACHE_NEED_AUTOMOUNT))
557 __managed_dentry_set_automount(dentry);
558 }
559 spin_unlock(&dentry->d_lock);
560 complete_all(&ino->expire_complete); 551 complete_all(&ino->expire_complete);
561 spin_unlock(&sbi->fs_lock); 552 spin_unlock(&sbi->fs_lock);
562 dput(dentry); 553 dput(dentry);
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 91b11650722e..30a6ab66e99a 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -355,7 +355,6 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
355 status = autofs4_mount_wait(dentry); 355 status = autofs4_mount_wait(dentry);
356 if (status) 356 if (status)
357 return ERR_PTR(status); 357 return ERR_PTR(status);
358 spin_lock(&sbi->fs_lock);
359 goto done; 358 goto done;
360 } 359 }
361 360
@@ -364,8 +363,11 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
364 * having d_mountpoint() true, so there's no need to call back 363 * having d_mountpoint() true, so there's no need to call back
365 * to the daemon. 364 * to the daemon.
366 */ 365 */
367 if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)) 366 if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)) {
367 spin_unlock(&sbi->fs_lock);
368 goto done; 368 goto done;
369 }
370
369 if (!d_mountpoint(dentry)) { 371 if (!d_mountpoint(dentry)) {
370 /* 372 /*
371 * It's possible that user space hasn't removed directories 373 * It's possible that user space hasn't removed directories
@@ -379,8 +381,10 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
379 * require user space behave. 381 * require user space behave.
380 */ 382 */
381 if (sbi->version > 4) { 383 if (sbi->version > 4) {
382 if (have_submounts(dentry)) 384 if (have_submounts(dentry)) {
385 spin_unlock(&sbi->fs_lock);
383 goto done; 386 goto done;
387 }
384 } else { 388 } else {
385 spin_lock(&dentry->d_lock); 389 spin_lock(&dentry->d_lock);
386 if (!list_empty(&dentry->d_subdirs)) { 390 if (!list_empty(&dentry->d_subdirs)) {
@@ -399,28 +403,8 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
399 return ERR_PTR(status); 403 return ERR_PTR(status);
400 } 404 }
401 } 405 }
402done:
403 if (!(ino->flags & AUTOFS_INF_EXPIRING)) {
404 /*
405 * Any needed mounting has been completed and the path
406 * updated so clear DCACHE_NEED_AUTOMOUNT so we don't
407 * call ->d_automount() on rootless multi-mounts since
408 * it can lead to an incorrect ELOOP error return.
409 *
410 * Only clear DMANAGED_AUTOMOUNT for rootless multi-mounts and
411 * symlinks as in all other cases the dentry will be covered by
412 * an actual mount so ->d_automount() won't be called during
413 * the follow.
414 */
415 spin_lock(&dentry->d_lock);
416 if ((!d_mountpoint(dentry) &&
417 !list_empty(&dentry->d_subdirs)) ||
418 (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)))
419 __managed_dentry_clear_automount(dentry);
420 spin_unlock(&dentry->d_lock);
421 }
422 spin_unlock(&sbi->fs_lock); 406 spin_unlock(&sbi->fs_lock);
423 407done:
424 /* Mount succeeded, check if we ended up with a new dentry */ 408 /* Mount succeeded, check if we ended up with a new dentry */
425 dentry = autofs4_mountpoint_changed(path); 409 dentry = autofs4_mountpoint_changed(path);
426 if (!dentry) 410 if (!dentry)
@@ -432,6 +416,8 @@ done:
432int autofs4_d_manage(struct dentry *dentry, bool rcu_walk) 416int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
433{ 417{
434 struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); 418 struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
419 struct autofs_info *ino = autofs4_dentry_ino(dentry);
420 int status;
435 421
436 DPRINTK("dentry=%p %.*s", 422 DPRINTK("dentry=%p %.*s",
437 dentry, dentry->d_name.len, dentry->d_name.name); 423 dentry, dentry->d_name.len, dentry->d_name.name);
@@ -456,7 +442,32 @@ int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
456 * This dentry may be under construction so wait on mount 442 * This dentry may be under construction so wait on mount
457 * completion. 443 * completion.
458 */ 444 */
459 return autofs4_mount_wait(dentry); 445 status = autofs4_mount_wait(dentry);
446 if (status)
447 return status;
448
449 spin_lock(&sbi->fs_lock);
450 /*
451 * If the dentry has been selected for expire while we slept
452 * on the lock then it might go away. We'll deal with that in
453 * ->d_automount() and wait on a new mount if the expire
454 * succeeds or return here if it doesn't (since there's no
455 * mount to follow with a rootless multi-mount).
456 */
457 if (!(ino->flags & AUTOFS_INF_EXPIRING)) {
458 /*
459 * Any needed mounting has been completed and the path
460 * updated so check if this is a rootless multi-mount so
461 * we can avoid needless calls ->d_automount() and avoid
462 * an incorrect ELOOP error return.
463 */
464 if ((!d_mountpoint(dentry) && !simple_empty(dentry)) ||
465 (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)))
466 status = -EISDIR;
467 }
468 spin_unlock(&sbi->fs_lock);
469
470 return status;
460} 471}
461 472
462/* Lookups in the root directory */ 473/* Lookups in the root directory */