aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorRam Pai <linuxram@us.ibm.com>2005-11-07 17:17:04 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-07 21:18:10 -0500
commit70fbcdf4d252c6b17cc249cb9ac9b220cb0b863d (patch)
treecefa087774953dd7a2181513427577286f8e9f63 /fs
parent5b83d2c5c0afcf5a3517cf00d9ceb41b8345e01b (diff)
[PATCH] umount_tree() locking change
umount is done under the protection of the namespace semaphore. This can lead to intresting deadlocks when the last reference to a mount is released, if filesystem code is in sufficiently nasty state. This collects all the to-be-released-mounts and releases them after releasing the namespace semaphore. That both reduces the time we are holding namespace semaphore and gets the things more robust. Idea proposed by Al Viro. Signed-off-by: Ram Pai <linuxram@us.ibm.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
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}