aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/namespace.c84
1 files changed, 51 insertions, 33 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index dfeeab964e84..c2ffa0f349fd 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -394,32 +394,45 @@ int may_umount(struct vfsmount *mnt)
394 394
395EXPORT_SYMBOL(may_umount); 395EXPORT_SYMBOL(may_umount);
396 396
397static void umount_tree(struct vfsmount *mnt) 397static void release_mounts(struct list_head *head)
398{
399 struct vfsmount *mnt;
400 while(!list_empty(head)) {
401 mnt = list_entry(head->next, struct vfsmount, mnt_hash);
402 list_del_init(&mnt->mnt_hash);
403 if (mnt->mnt_parent != mnt) {
404 struct dentry *dentry;
405 struct vfsmount *m;
406 spin_lock(&vfsmount_lock);
407 dentry = mnt->mnt_mountpoint;
408 m = mnt->mnt_parent;
409 mnt->mnt_mountpoint = mnt->mnt_root;
410 mnt->mnt_parent = mnt;
411 spin_unlock(&vfsmount_lock);
412 dput(dentry);
413 mntput(m);
414 }
415 mntput(mnt);
416 }
417}
418
419static void umount_tree(struct vfsmount *mnt, struct list_head *kill)
398{ 420{
399 struct vfsmount *p; 421 struct vfsmount *p;
400 LIST_HEAD(kill);
401 422
402 for (p = mnt; p; p = next_mnt(p, mnt)) { 423 for (p = mnt; p; p = next_mnt(p, mnt)) {
403 list_del(&p->mnt_list); 424 list_del(&p->mnt_hash);
404 list_add(&p->mnt_list, &kill); 425 list_add(&p->mnt_hash, kill);
405 __touch_namespace(p->mnt_namespace);
406 p->mnt_namespace = NULL;
407 } 426 }
408 427
409 while (!list_empty(&kill)) { 428 list_for_each_entry(p, kill, mnt_hash) {
410 mnt = list_entry(kill.next, struct vfsmount, mnt_list); 429 list_del_init(&p->mnt_expire);
411 list_del_init(&mnt->mnt_list); 430 list_del_init(&p->mnt_list);
412 list_del_init(&mnt->mnt_expire); 431 __touch_namespace(p->mnt_namespace);
413 if (mnt->mnt_parent == mnt) { 432 p->mnt_namespace = NULL;
414 spin_unlock(&vfsmount_lock); 433 list_del_init(&p->mnt_child);
415 } else { 434 if (p->mnt_parent != p)
416 struct nameidata old_nd; 435 mnt->mnt_mountpoint->d_mounted--;
417 detach_mnt(mnt, &old_nd);
418 spin_unlock(&vfsmount_lock);
419 path_release(&old_nd);
420 }
421 mntput(mnt);
422 spin_lock(&vfsmount_lock);
423 } 436 }
424} 437}
425 438
@@ -427,6 +440,7 @@ static int do_umount(struct vfsmount *mnt, int flags)
427{ 440{
428 struct super_block *sb = mnt->mnt_sb; 441 struct super_block *sb = mnt->mnt_sb;
429 int retval; 442 int retval;
443 LIST_HEAD(umount_list);
430 444
431 retval = security_sb_umount(mnt, flags); 445 retval = security_sb_umount(mnt, flags);
432 if (retval) 446 if (retval)
@@ -497,13 +511,14 @@ static int do_umount(struct vfsmount *mnt, int flags)
497 retval = -EBUSY; 511 retval = -EBUSY;
498 if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) { 512 if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) {
499 if (!list_empty(&mnt->mnt_list)) 513 if (!list_empty(&mnt->mnt_list))
500 umount_tree(mnt); 514 umount_tree(mnt, &umount_list);
501 retval = 0; 515 retval = 0;
502 } 516 }
503 spin_unlock(&vfsmount_lock); 517 spin_unlock(&vfsmount_lock);
504 if (retval) 518 if (retval)
505 security_sb_umount_busy(mnt); 519 security_sb_umount_busy(mnt);
506 up_write(&current->namespace->sem); 520 up_write(&current->namespace->sem);
521 release_mounts(&umount_list);
507 return retval; 522 return retval;
508} 523}
509 524
@@ -616,9 +631,11 @@ static struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry)
616 return res; 631 return res;
617Enomem: 632Enomem:
618 if (res) { 633 if (res) {
634 LIST_HEAD(umount_list);
619 spin_lock(&vfsmount_lock); 635 spin_lock(&vfsmount_lock);
620 umount_tree(res); 636 umount_tree(res, &umount_list);
621 spin_unlock(&vfsmount_lock); 637 spin_unlock(&vfsmount_lock);
638 release_mounts(&umount_list);
622 } 639 }
623 return NULL; 640 return NULL;
624} 641}
@@ -698,9 +715,11 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse)
698 715
699 err = graft_tree(mnt, nd); 716 err = graft_tree(mnt, nd);
700 if (err) { 717 if (err) {
718 LIST_HEAD(umount_list);
701 spin_lock(&vfsmount_lock); 719 spin_lock(&vfsmount_lock);
702 umount_tree(mnt); 720 umount_tree(mnt, &umount_list);
703 spin_unlock(&vfsmount_lock); 721 spin_unlock(&vfsmount_lock);
722 release_mounts(&umount_list);
704 } 723 }
705 724
706out: 725out:
@@ -875,7 +894,8 @@ unlock:
875 894
876EXPORT_SYMBOL_GPL(do_add_mount); 895EXPORT_SYMBOL_GPL(do_add_mount);
877 896
878static void expire_mount(struct vfsmount *mnt, struct list_head *mounts) 897static void expire_mount(struct vfsmount *mnt, struct list_head *mounts,
898 struct list_head *umounts)
879{ 899{
880 spin_lock(&vfsmount_lock); 900 spin_lock(&vfsmount_lock);
881 901
@@ -893,16 +913,12 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts)
893 * contributed by the vfsmount parent and the mntget above 913 * contributed by the vfsmount parent and the mntget above
894 */ 914 */
895 if (atomic_read(&mnt->mnt_count) == 2) { 915 if (atomic_read(&mnt->mnt_count) == 2) {
896 struct nameidata old_nd;
897
898 /* delete from the namespace */ 916 /* delete from the namespace */
899 touch_namespace(mnt->mnt_namespace); 917 touch_namespace(mnt->mnt_namespace);
900 list_del_init(&mnt->mnt_list); 918 list_del_init(&mnt->mnt_list);
901 mnt->mnt_namespace = NULL; 919 mnt->mnt_namespace = NULL;
902 detach_mnt(mnt, &old_nd); 920 umount_tree(mnt, umounts);
903 spin_unlock(&vfsmount_lock); 921 spin_unlock(&vfsmount_lock);
904 path_release(&old_nd);
905 mntput(mnt);
906 } else { 922 } else {
907 /* 923 /*
908 * Someone brought it back to life whilst we didn't have any 924 * Someone brought it back to life whilst we didn't have any
@@ -951,6 +967,7 @@ void mark_mounts_for_expiry(struct list_head *mounts)
951 * - dispose of the corpse 967 * - dispose of the corpse
952 */ 968 */
953 while (!list_empty(&graveyard)) { 969 while (!list_empty(&graveyard)) {
970 LIST_HEAD(umounts);
954 mnt = list_entry(graveyard.next, struct vfsmount, mnt_expire); 971 mnt = list_entry(graveyard.next, struct vfsmount, mnt_expire);
955 list_del_init(&mnt->mnt_expire); 972 list_del_init(&mnt->mnt_expire);
956 973
@@ -963,12 +980,11 @@ void mark_mounts_for_expiry(struct list_head *mounts)
963 980
964 spin_unlock(&vfsmount_lock); 981 spin_unlock(&vfsmount_lock);
965 down_write(&namespace->sem); 982 down_write(&namespace->sem);
966 expire_mount(mnt, mounts); 983 expire_mount(mnt, mounts, &umounts);
967 up_write(&namespace->sem); 984 up_write(&namespace->sem);
968 985 release_mounts(&umounts);
969 mntput(mnt); 986 mntput(mnt);
970 put_namespace(namespace); 987 put_namespace(namespace);
971
972 spin_lock(&vfsmount_lock); 988 spin_lock(&vfsmount_lock);
973 } 989 }
974 990
@@ -1508,12 +1524,14 @@ void __init mnt_init(unsigned long mempages)
1508void __put_namespace(struct namespace *namespace) 1524void __put_namespace(struct namespace *namespace)
1509{ 1525{
1510 struct vfsmount *root = namespace->root; 1526 struct vfsmount *root = namespace->root;
1527 LIST_HEAD(umount_list);
1511 namespace->root = NULL; 1528 namespace->root = NULL;
1512 spin_unlock(&vfsmount_lock); 1529 spin_unlock(&vfsmount_lock);
1513 down_write(&namespace->sem); 1530 down_write(&namespace->sem);
1514 spin_lock(&vfsmount_lock); 1531 spin_lock(&vfsmount_lock);
1515 umount_tree(root); 1532 umount_tree(root, &umount_list);
1516 spin_unlock(&vfsmount_lock); 1533 spin_unlock(&vfsmount_lock);
1517 up_write(&namespace->sem); 1534 up_write(&namespace->sem);
1535 release_mounts(&umount_list);
1518 kfree(namespace); 1536 kfree(namespace);
1519} 1537}