aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namespace.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c130
1 files changed, 67 insertions, 63 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 208c079e9fdb..587eb0d707ee 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -61,7 +61,7 @@ struct vfsmount *alloc_vfsmnt(const char *name)
61 INIT_LIST_HEAD(&mnt->mnt_child); 61 INIT_LIST_HEAD(&mnt->mnt_child);
62 INIT_LIST_HEAD(&mnt->mnt_mounts); 62 INIT_LIST_HEAD(&mnt->mnt_mounts);
63 INIT_LIST_HEAD(&mnt->mnt_list); 63 INIT_LIST_HEAD(&mnt->mnt_list);
64 INIT_LIST_HEAD(&mnt->mnt_fslink); 64 INIT_LIST_HEAD(&mnt->mnt_expire);
65 if (name) { 65 if (name) {
66 int size = strlen(name)+1; 66 int size = strlen(name)+1;
67 char *newname = kmalloc(size, GFP_KERNEL); 67 char *newname = kmalloc(size, GFP_KERNEL);
@@ -165,8 +165,8 @@ clone_mnt(struct vfsmount *old, struct dentry *root)
165 /* stick the duplicate mount on the same expiry list 165 /* stick the duplicate mount on the same expiry list
166 * as the original if that was on one */ 166 * as the original if that was on one */
167 spin_lock(&vfsmount_lock); 167 spin_lock(&vfsmount_lock);
168 if (!list_empty(&old->mnt_fslink)) 168 if (!list_empty(&old->mnt_expire))
169 list_add(&mnt->mnt_fslink, &old->mnt_fslink); 169 list_add(&mnt->mnt_expire, &old->mnt_expire);
170 spin_unlock(&vfsmount_lock); 170 spin_unlock(&vfsmount_lock);
171 } 171 }
172 return mnt; 172 return mnt;
@@ -345,12 +345,13 @@ static void umount_tree(struct vfsmount *mnt)
345 for (p = mnt; p; p = next_mnt(p, mnt)) { 345 for (p = mnt; p; p = next_mnt(p, mnt)) {
346 list_del(&p->mnt_list); 346 list_del(&p->mnt_list);
347 list_add(&p->mnt_list, &kill); 347 list_add(&p->mnt_list, &kill);
348 p->mnt_namespace = NULL;
348 } 349 }
349 350
350 while (!list_empty(&kill)) { 351 while (!list_empty(&kill)) {
351 mnt = list_entry(kill.next, struct vfsmount, mnt_list); 352 mnt = list_entry(kill.next, struct vfsmount, mnt_list);
352 list_del_init(&mnt->mnt_list); 353 list_del_init(&mnt->mnt_list);
353 list_del_init(&mnt->mnt_fslink); 354 list_del_init(&mnt->mnt_expire);
354 if (mnt->mnt_parent == mnt) { 355 if (mnt->mnt_parent == mnt) {
355 spin_unlock(&vfsmount_lock); 356 spin_unlock(&vfsmount_lock);
356 } else { 357 } else {
@@ -644,7 +645,7 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse)
644 if (mnt) { 645 if (mnt) {
645 /* stop bind mounts from expiring */ 646 /* stop bind mounts from expiring */
646 spin_lock(&vfsmount_lock); 647 spin_lock(&vfsmount_lock);
647 list_del_init(&mnt->mnt_fslink); 648 list_del_init(&mnt->mnt_expire);
648 spin_unlock(&vfsmount_lock); 649 spin_unlock(&vfsmount_lock);
649 650
650 err = graft_tree(mnt, nd); 651 err = graft_tree(mnt, nd);
@@ -743,7 +744,7 @@ static int do_move_mount(struct nameidata *nd, char *old_name)
743 744
744 /* if the mount is moved, it should no longer be expire 745 /* if the mount is moved, it should no longer be expire
745 * automatically */ 746 * automatically */
746 list_del_init(&old_nd.mnt->mnt_fslink); 747 list_del_init(&old_nd.mnt->mnt_expire);
747out2: 748out2:
748 spin_unlock(&vfsmount_lock); 749 spin_unlock(&vfsmount_lock);
749out1: 750out1:
@@ -807,12 +808,13 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd,
807 goto unlock; 808 goto unlock;
808 809
809 newmnt->mnt_flags = mnt_flags; 810 newmnt->mnt_flags = mnt_flags;
811 newmnt->mnt_namespace = current->namespace;
810 err = graft_tree(newmnt, nd); 812 err = graft_tree(newmnt, nd);
811 813
812 if (err == 0 && fslist) { 814 if (err == 0 && fslist) {
813 /* add to the specified expiration list */ 815 /* add to the specified expiration list */
814 spin_lock(&vfsmount_lock); 816 spin_lock(&vfsmount_lock);
815 list_add_tail(&newmnt->mnt_fslink, fslist); 817 list_add_tail(&newmnt->mnt_expire, fslist);
816 spin_unlock(&vfsmount_lock); 818 spin_unlock(&vfsmount_lock);
817 } 819 }
818 820
@@ -824,6 +826,54 @@ unlock:
824 826
825EXPORT_SYMBOL_GPL(do_add_mount); 827EXPORT_SYMBOL_GPL(do_add_mount);
826 828
829static void expire_mount(struct vfsmount *mnt, struct list_head *mounts)
830{
831 spin_lock(&vfsmount_lock);
832
833 /*
834 * Check if mount is still attached, if not, let whoever holds it deal
835 * with the sucker
836 */
837 if (mnt->mnt_parent == mnt) {
838 spin_unlock(&vfsmount_lock);
839 return;
840 }
841
842 /*
843 * Check that it is still dead: the count should now be 2 - as
844 * contributed by the vfsmount parent and the mntget above
845 */
846 if (atomic_read(&mnt->mnt_count) == 2) {
847 struct nameidata old_nd;
848
849 /* delete from the namespace */
850 list_del_init(&mnt->mnt_list);
851 mnt->mnt_namespace = NULL;
852 detach_mnt(mnt, &old_nd);
853 spin_unlock(&vfsmount_lock);
854 path_release(&old_nd);
855
856 /*
857 * Now lay it to rest if this was the last ref on the superblock
858 */
859 if (atomic_read(&mnt->mnt_sb->s_active) == 1) {
860 /* last instance - try to be smart */
861 lock_kernel();
862 DQUOT_OFF(mnt->mnt_sb);
863 acct_auto_close(mnt->mnt_sb);
864 unlock_kernel();
865 }
866 mntput(mnt);
867 } else {
868 /*
869 * Someone brought it back to life whilst we didn't have any
870 * locks held so return it to the expiration list
871 */
872 list_add_tail(&mnt->mnt_expire, mounts);
873 spin_unlock(&vfsmount_lock);
874 }
875}
876
827/* 877/*
828 * process a list of expirable mountpoints with the intent of discarding any 878 * process a list of expirable mountpoints with the intent of discarding any
829 * mountpoints that aren't in use and haven't been touched since last we came 879 * mountpoints that aren't in use and haven't been touched since last we came
@@ -846,13 +896,13 @@ void mark_mounts_for_expiry(struct list_head *mounts)
846 * - still marked for expiry (marked on the last call here; marks are 896 * - still marked for expiry (marked on the last call here; marks are
847 * cleared by mntput()) 897 * cleared by mntput())
848 */ 898 */
849 list_for_each_entry_safe(mnt, next, mounts, mnt_fslink) { 899 list_for_each_entry_safe(mnt, next, mounts, mnt_expire) {
850 if (!xchg(&mnt->mnt_expiry_mark, 1) || 900 if (!xchg(&mnt->mnt_expiry_mark, 1) ||
851 atomic_read(&mnt->mnt_count) != 1) 901 atomic_read(&mnt->mnt_count) != 1)
852 continue; 902 continue;
853 903
854 mntget(mnt); 904 mntget(mnt);
855 list_move(&mnt->mnt_fslink, &graveyard); 905 list_move(&mnt->mnt_expire, &graveyard);
856 } 906 }
857 907
858 /* 908 /*
@@ -862,61 +912,19 @@ void mark_mounts_for_expiry(struct list_head *mounts)
862 * - dispose of the corpse 912 * - dispose of the corpse
863 */ 913 */
864 while (!list_empty(&graveyard)) { 914 while (!list_empty(&graveyard)) {
865 mnt = list_entry(graveyard.next, struct vfsmount, mnt_fslink); 915 mnt = list_entry(graveyard.next, struct vfsmount, mnt_expire);
866 list_del_init(&mnt->mnt_fslink); 916 list_del_init(&mnt->mnt_expire);
867 917
868 /* don't do anything if the namespace is dead - all the 918 /* don't do anything if the namespace is dead - all the
869 * vfsmounts from it are going away anyway */ 919 * vfsmounts from it are going away anyway */
870 namespace = mnt->mnt_namespace; 920 namespace = mnt->mnt_namespace;
871 if (!namespace || atomic_read(&namespace->count) <= 0) 921 if (!namespace || !namespace->root)
872 continue; 922 continue;
873 get_namespace(namespace); 923 get_namespace(namespace);
874 924
875 spin_unlock(&vfsmount_lock); 925 spin_unlock(&vfsmount_lock);
876 down_write(&namespace->sem); 926 down_write(&namespace->sem);
877 spin_lock(&vfsmount_lock); 927 expire_mount(mnt, mounts);
878
879 /* check that it is still dead: the count should now be 2 - as
880 * contributed by the vfsmount parent and the mntget above */
881 if (atomic_read(&mnt->mnt_count) == 2) {
882 struct vfsmount *xdmnt;
883 struct dentry *xdentry;
884
885 /* delete from the namespace */
886 list_del_init(&mnt->mnt_list);
887 list_del_init(&mnt->mnt_child);
888 list_del_init(&mnt->mnt_hash);
889 mnt->mnt_mountpoint->d_mounted--;
890
891 xdentry = mnt->mnt_mountpoint;
892 mnt->mnt_mountpoint = mnt->mnt_root;
893 xdmnt = mnt->mnt_parent;
894 mnt->mnt_parent = mnt;
895
896 spin_unlock(&vfsmount_lock);
897
898 mntput(xdmnt);
899 dput(xdentry);
900
901 /* now lay it to rest if this was the last ref on the
902 * superblock */
903 if (atomic_read(&mnt->mnt_sb->s_active) == 1) {
904 /* last instance - try to be smart */
905 lock_kernel();
906 DQUOT_OFF(mnt->mnt_sb);
907 acct_auto_close(mnt->mnt_sb);
908 unlock_kernel();
909 }
910
911 mntput(mnt);
912 } else {
913 /* someone brought it back to life whilst we didn't
914 * have any locks held so return it to the expiration
915 * list */
916 list_add_tail(&mnt->mnt_fslink, mounts);
917 spin_unlock(&vfsmount_lock);
918 }
919
920 up_write(&namespace->sem); 928 up_write(&namespace->sem);
921 929
922 mntput(mnt); 930 mntput(mnt);
@@ -1449,16 +1457,12 @@ void __init mnt_init(unsigned long mempages)
1449 1457
1450void __put_namespace(struct namespace *namespace) 1458void __put_namespace(struct namespace *namespace)
1451{ 1459{
1452 struct vfsmount *mnt; 1460 struct vfsmount *root = namespace->root;
1453 1461 namespace->root = NULL;
1462 spin_unlock(&vfsmount_lock);
1454 down_write(&namespace->sem); 1463 down_write(&namespace->sem);
1455 spin_lock(&vfsmount_lock); 1464 spin_lock(&vfsmount_lock);
1456 1465 umount_tree(root);
1457 list_for_each_entry(mnt, &namespace->list, mnt_list) {
1458 mnt->mnt_namespace = NULL;
1459 }
1460
1461 umount_tree(namespace->root);
1462 spin_unlock(&vfsmount_lock); 1466 spin_unlock(&vfsmount_lock);
1463 up_write(&namespace->sem); 1467 up_write(&namespace->sem);
1464 kfree(namespace); 1468 kfree(namespace);