diff options
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 71 |
1 files changed, 39 insertions, 32 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index ea555a36c314..d82cf18a1a94 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -825,6 +825,44 @@ unlock: | |||
825 | 825 | ||
826 | EXPORT_SYMBOL_GPL(do_add_mount); | 826 | EXPORT_SYMBOL_GPL(do_add_mount); |
827 | 827 | ||
828 | static void expire_mount(struct vfsmount *mnt, struct list_head *mounts) | ||
829 | { | ||
830 | spin_lock(&vfsmount_lock); | ||
831 | |||
832 | /* | ||
833 | * Check that it is still dead: the count should now be 2 - as | ||
834 | * contributed by the vfsmount parent and the mntget above | ||
835 | */ | ||
836 | if (atomic_read(&mnt->mnt_count) == 2) { | ||
837 | struct nameidata old_nd; | ||
838 | |||
839 | /* delete from the namespace */ | ||
840 | list_del_init(&mnt->mnt_list); | ||
841 | detach_mnt(mnt, &old_nd); | ||
842 | spin_unlock(&vfsmount_lock); | ||
843 | path_release(&old_nd); | ||
844 | |||
845 | /* | ||
846 | * Now lay it to rest if this was the last ref on the superblock | ||
847 | */ | ||
848 | if (atomic_read(&mnt->mnt_sb->s_active) == 1) { | ||
849 | /* last instance - try to be smart */ | ||
850 | lock_kernel(); | ||
851 | DQUOT_OFF(mnt->mnt_sb); | ||
852 | acct_auto_close(mnt->mnt_sb); | ||
853 | unlock_kernel(); | ||
854 | } | ||
855 | mntput(mnt); | ||
856 | } else { | ||
857 | /* | ||
858 | * Someone brought it back to life whilst we didn't have any | ||
859 | * locks held so return it to the expiration list | ||
860 | */ | ||
861 | list_add_tail(&mnt->mnt_fslink, mounts); | ||
862 | spin_unlock(&vfsmount_lock); | ||
863 | } | ||
864 | } | ||
865 | |||
828 | /* | 866 | /* |
829 | * process a list of expirable mountpoints with the intent of discarding any | 867 | * process a list of expirable mountpoints with the intent of discarding any |
830 | * mountpoints that aren't in use and haven't been touched since last we came | 868 | * mountpoints that aren't in use and haven't been touched since last we came |
@@ -875,38 +913,7 @@ void mark_mounts_for_expiry(struct list_head *mounts) | |||
875 | 913 | ||
876 | spin_unlock(&vfsmount_lock); | 914 | spin_unlock(&vfsmount_lock); |
877 | down_write(&namespace->sem); | 915 | down_write(&namespace->sem); |
878 | spin_lock(&vfsmount_lock); | 916 | expire_mount(mnt, mounts); |
879 | |||
880 | /* check that it is still dead: the count should now be 2 - as | ||
881 | * contributed by the vfsmount parent and the mntget above */ | ||
882 | if (atomic_read(&mnt->mnt_count) == 2) { | ||
883 | struct nameidata old_nd; | ||
884 | |||
885 | /* delete from the namespace */ | ||
886 | list_del_init(&mnt->mnt_list); | ||
887 | detach_mnt(mnt, &old_nd); | ||
888 | spin_unlock(&vfsmount_lock); | ||
889 | path_release(&old_nd); | ||
890 | |||
891 | /* now lay it to rest if this was the last ref on the | ||
892 | * superblock */ | ||
893 | if (atomic_read(&mnt->mnt_sb->s_active) == 1) { | ||
894 | /* last instance - try to be smart */ | ||
895 | lock_kernel(); | ||
896 | DQUOT_OFF(mnt->mnt_sb); | ||
897 | acct_auto_close(mnt->mnt_sb); | ||
898 | unlock_kernel(); | ||
899 | } | ||
900 | |||
901 | mntput(mnt); | ||
902 | } else { | ||
903 | /* someone brought it back to life whilst we didn't | ||
904 | * have any locks held so return it to the expiration | ||
905 | * list */ | ||
906 | list_add_tail(&mnt->mnt_fslink, mounts); | ||
907 | spin_unlock(&vfsmount_lock); | ||
908 | } | ||
909 | |||
910 | up_write(&namespace->sem); | 917 | up_write(&namespace->sem); |
911 | 918 | ||
912 | mntput(mnt); | 919 | mntput(mnt); |