aboutsummaryrefslogtreecommitdiffstats
path: root/fs/autofs4/root.c
diff options
context:
space:
mode:
authorIan Kent <raven@themaw.net>2011-01-14 13:46:03 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2011-01-15 20:07:38 -0500
commitb5b801779d59165c4ecf1009009109545bd1f642 (patch)
tree3a1c8b2e65e72977993ba96c1398edba4c63cbf5 /fs/autofs4/root.c
parent10584211e48036182212b598cc53331776406d60 (diff)
autofs4: Add d_manage() dentry operation
This patch required a previous patch to add the ->d_automount() dentry operation. Add a function to use the newly defined ->d_manage() dentry operation for blocking during mount and expire. Whether the VFS calls the dentry operations d_automount() and d_manage() is controled by the DMANAGED_AUTOMOUNT and DMANAGED_TRANSIT flags. autofs uses the d_automount() operation to callback to user space to request mount operations and the d_manage() operation to block walks into mounts that are under construction or destruction. In order to prevent these functions from being called unnecessarily the DMANAGED_* flags are cleared for cases which would cause this. In the common case the DMANAGED_AUTOMOUNT and DMANAGED_TRANSIT flags are both set for dentrys waiting to be mounted. The DMANAGED_TRANSIT flag is cleared upon successful mount request completion and set during expire runs, both during the dentry expire check, and if selected for expire, is left set until a subsequent successful mount request completes. The exception to this is the so-called rootless multi-mount which has no actual mount at its base. In this case the DMANAGED_AUTOMOUNT flag is cleared upon successful mount request completion as well and set again after a successful expire. Signed-off-by: Ian Kent <raven@themaw.net> Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/autofs4/root.c')
-rw-r--r--fs/autofs4/root.c95
1 files changed, 82 insertions, 13 deletions
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 27dc53e111fd..f1076b91a0fa 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -424,6 +424,7 @@ static const struct dentry_operations autofs4_root_dentry_operations = {
424/* For other dentries */ 424/* For other dentries */
425static const struct dentry_operations autofs4_dentry_operations = { 425static const struct dentry_operations autofs4_dentry_operations = {
426 .d_automount = autofs4_d_automount, 426 .d_automount = autofs4_d_automount,
427 .d_manage = autofs4_d_manage,
427 .d_release = autofs4_dentry_release, 428 .d_release = autofs4_dentry_release,
428}; 429};
429 430
@@ -604,6 +605,18 @@ struct vfsmount *autofs4_d_automount(struct path *path)
604 DPRINTK("dentry=%p %.*s", 605 DPRINTK("dentry=%p %.*s",
605 dentry, dentry->d_name.len, dentry->d_name.name); 606 dentry, dentry->d_name.len, dentry->d_name.name);
606 607
608 /*
609 * Someone may have manually umounted this or it was a submount
610 * that has gone away.
611 */
612 spin_lock(&dentry->d_lock);
613 if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) {
614 if (!(dentry->d_flags & DCACHE_MANAGE_TRANSIT) &&
615 (dentry->d_flags & DCACHE_NEED_AUTOMOUNT))
616 __managed_dentry_set_transit(path->dentry);
617 }
618 spin_unlock(&dentry->d_lock);
619
607 /* The daemon never triggers a mount. */ 620 /* The daemon never triggers a mount. */
608 if (autofs4_oz_mode(sbi)) 621 if (autofs4_oz_mode(sbi))
609 return NULL; 622 return NULL;
@@ -633,31 +646,63 @@ struct vfsmount *autofs4_d_automount(struct path *path)
633 646
634 /* 647 /*
635 * If the dentry is a symlink it's equivalent to a directory 648 * If the dentry is a symlink it's equivalent to a directory
636 * having d_mounted() true, so there's no need to call back 649 * having d_mountpoint() true, so there's no need to call back
637 * to the daemon. 650 * to the daemon.
638 */ 651 */
639 if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)) 652 if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode))
640 goto done; 653 goto done;
641 spin_lock(&dentry->d_lock); 654 if (!d_mountpoint(dentry)) {
642 if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) { 655 /*
656 * It's possible that user space hasn't removed directories
657 * after umounting a rootless multi-mount, although it
658 * should. For v5 have_submounts() is sufficient to handle
659 * this because the leaves of the directory tree under the
660 * mount never trigger mounts themselves (they have an autofs
661 * trigger mount mounted on them). But v4 pseudo direct mounts
662 * do need the leaves to to trigger mounts. In this case we
663 * have no choice but to use the list_empty() check and
664 * require user space behave.
665 */
666 if (sbi->version > 4) {
667 if (have_submounts(dentry))
668 goto done;
669 } else {
670 spin_lock(&dentry->d_lock);
671 if (!list_empty(&dentry->d_subdirs)) {
672 spin_unlock(&dentry->d_lock);
673 goto done;
674 }
675 spin_unlock(&dentry->d_lock);
676 }
643 ino->flags |= AUTOFS_INF_PENDING; 677 ino->flags |= AUTOFS_INF_PENDING;
644 spin_unlock(&dentry->d_lock);
645 spin_unlock(&sbi->fs_lock); 678 spin_unlock(&sbi->fs_lock);
646 status = autofs4_mount_wait(dentry); 679 status = autofs4_mount_wait(dentry);
647 if (status) 680 if (status)
648 return ERR_PTR(status); 681 return ERR_PTR(status);
649 spin_lock(&sbi->fs_lock); 682 spin_lock(&sbi->fs_lock);
650 ino->flags &= ~AUTOFS_INF_PENDING; 683 ino->flags &= ~AUTOFS_INF_PENDING;
651 goto done;
652 } 684 }
653 spin_unlock(&dentry->d_lock);
654done: 685done:
655 /* 686 if (!(ino->flags & AUTOFS_INF_EXPIRING)) {
656 * Any needed mounting has been completed and the path updated 687 /*
657 * so turn this into a normal dentry so we don't continually 688 * Any needed mounting has been completed and the path updated
658 * call ->d_automount(). 689 * so turn this into a normal dentry so we don't continually
659 */ 690 * call ->d_automount() and ->d_manage().
660 managed_dentry_clear_automount(dentry); 691 */
692 spin_lock(&dentry->d_lock);
693 __managed_dentry_clear_transit(dentry);
694 /*
695 * Only clear DMANAGED_AUTOMOUNT for rootless multi-mounts and
696 * symlinks as in all other cases the dentry will be covered by
697 * an actual mount so ->d_automount() won't be called during
698 * the follow.
699 */
700 if ((!d_mountpoint(dentry) &&
701 !list_empty(&dentry->d_subdirs)) ||
702 (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)))
703 __managed_dentry_clear_automount(dentry);
704 spin_unlock(&dentry->d_lock);
705 }
661 spin_unlock(&sbi->fs_lock); 706 spin_unlock(&sbi->fs_lock);
662 707
663 /* Mount succeeded, check if we ended up with a new dentry */ 708 /* Mount succeeded, check if we ended up with a new dentry */
@@ -668,6 +713,30 @@ done:
668 return NULL; 713 return NULL;
669} 714}
670 715
716int autofs4_d_manage(struct dentry *dentry, bool mounting_here)
717{
718 struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
719
720 DPRINTK("dentry=%p %.*s",
721 dentry, dentry->d_name.len, dentry->d_name.name);
722
723 /* The daemon never waits. */
724 if (autofs4_oz_mode(sbi) || mounting_here) {
725 if (!d_mountpoint(dentry))
726 return -EISDIR;
727 return 0;
728 }
729
730 /* Wait for pending expires */
731 do_expire_wait(dentry);
732
733 /*
734 * This dentry may be under construction so wait on mount
735 * completion.
736 */
737 return autofs4_mount_wait(dentry);
738}
739
671/* Lookups in the root directory */ 740/* Lookups in the root directory */
672static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) 741static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
673{ 742{
@@ -704,7 +773,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
704 /* Mark entries in the root as mount triggers */ 773 /* Mark entries in the root as mount triggers */
705 if (autofs_type_indirect(sbi->type) && IS_ROOT(dentry->d_parent)) { 774 if (autofs_type_indirect(sbi->type) && IS_ROOT(dentry->d_parent)) {
706 d_set_d_op(dentry, &autofs4_dentry_operations); 775 d_set_d_op(dentry, &autofs4_dentry_operations);
707 managed_dentry_set_automount(dentry); 776 __managed_dentry_set_managed(dentry);
708 } 777 }
709 778
710 ino = autofs4_init_ino(NULL, sbi, 0555); 779 ino = autofs4_init_ino(NULL, sbi, 0555);