aboutsummaryrefslogtreecommitdiffstats
path: root/fs/autofs4/root.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/autofs4/root.c')
-rw-r--r--fs/autofs4/root.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 8315565ed7d4..9194e274f849 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -630,6 +630,58 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
630 return 0; 630 return 0;
631} 631}
632 632
633/*
634 * Version 4 of autofs provides a pseudo direct mount implementation
635 * that relies on directories at the leaves of a directory tree under
636 * an indirect mount to trigger mounts. To allow for this we need to
637 * set the DMANAGED_AUTOMOUNT and DMANAGED_TRANSIT flags on the leaves
638 * of the directory tree. There is no need to clear the automount flag
639 * following a mount or restore it after an expire because these mounts
640 * are always covered. However, it is neccessary to ensure that these
641 * flags are clear on non-empty directories to avoid unnecessary calls
642 * during path walks.
643 */
644static void autofs_set_leaf_automount_flags(struct dentry *dentry)
645{
646 struct dentry *parent;
647
648 /* root and dentrys in the root are already handled */
649 if (IS_ROOT(dentry->d_parent))
650 return;
651
652 managed_dentry_set_managed(dentry);
653
654 parent = dentry->d_parent;
655 /* only consider parents below dentrys in the root */
656 if (IS_ROOT(parent->d_parent))
657 return;
658 managed_dentry_clear_managed(parent);
659 return;
660}
661
662static void autofs_clear_leaf_automount_flags(struct dentry *dentry)
663{
664 struct list_head *d_child;
665 struct dentry *parent;
666
667 /* flags for dentrys in the root are handled elsewhere */
668 if (IS_ROOT(dentry->d_parent))
669 return;
670
671 managed_dentry_clear_managed(dentry);
672
673 parent = dentry->d_parent;
674 /* only consider parents below dentrys in the root */
675 if (IS_ROOT(parent->d_parent))
676 return;
677 d_child = &dentry->d_u.d_child;
678 /* Set parent managed if it's becoming empty */
679 if (d_child->next == &parent->d_subdirs &&
680 d_child->prev == &parent->d_subdirs)
681 managed_dentry_set_managed(parent);
682 return;
683}
684
633static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry) 685static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
634{ 686{
635 struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); 687 struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
@@ -657,6 +709,9 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
657 spin_unlock(&dentry->d_lock); 709 spin_unlock(&dentry->d_lock);
658 spin_unlock(&autofs4_lock); 710 spin_unlock(&autofs4_lock);
659 711
712 if (sbi->version < 5)
713 autofs_clear_leaf_automount_flags(dentry);
714
660 if (atomic_dec_and_test(&ino->count)) { 715 if (atomic_dec_and_test(&ino->count)) {
661 p_ino = autofs4_dentry_ino(dentry->d_parent); 716 p_ino = autofs4_dentry_ino(dentry->d_parent);
662 if (p_ino && dentry->d_parent != dentry) 717 if (p_ino && dentry->d_parent != dentry)
@@ -699,6 +754,9 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)
699 } 754 }
700 d_add(dentry, inode); 755 d_add(dentry, inode);
701 756
757 if (sbi->version < 5)
758 autofs_set_leaf_automount_flags(dentry);
759
702 dentry->d_fsdata = ino; 760 dentry->d_fsdata = ino;
703 ino->dentry = dget(dentry); 761 ino->dentry = dget(dentry);
704 atomic_inc(&ino->count); 762 atomic_inc(&ino->count);