diff options
-rw-r--r-- | fs/namespace.c | 41 |
1 files changed, 22 insertions, 19 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 1d83302f30c3..611f777bbd61 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -661,29 +661,32 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) | |||
661 | 661 | ||
662 | down_write(¤t->namespace->sem); | 662 | down_write(¤t->namespace->sem); |
663 | err = -EINVAL; | 663 | err = -EINVAL; |
664 | if (check_mnt(nd->mnt) && (!recurse || check_mnt(old_nd.mnt))) { | 664 | if (!check_mnt(nd->mnt) || !check_mnt(old_nd.mnt)) |
665 | err = -ENOMEM; | 665 | goto out; |
666 | if (recurse) | ||
667 | mnt = copy_tree(old_nd.mnt, old_nd.dentry); | ||
668 | else | ||
669 | mnt = clone_mnt(old_nd.mnt, old_nd.dentry); | ||
670 | } | ||
671 | 666 | ||
672 | if (mnt) { | 667 | err = -ENOMEM; |
673 | /* stop bind mounts from expiring */ | 668 | if (recurse) |
669 | mnt = copy_tree(old_nd.mnt, old_nd.dentry); | ||
670 | else | ||
671 | mnt = clone_mnt(old_nd.mnt, old_nd.dentry); | ||
672 | |||
673 | if (!mnt) | ||
674 | goto out; | ||
675 | |||
676 | /* stop bind mounts from expiring */ | ||
677 | spin_lock(&vfsmount_lock); | ||
678 | list_del_init(&mnt->mnt_expire); | ||
679 | spin_unlock(&vfsmount_lock); | ||
680 | |||
681 | err = graft_tree(mnt, nd); | ||
682 | if (err) { | ||
674 | spin_lock(&vfsmount_lock); | 683 | spin_lock(&vfsmount_lock); |
675 | list_del_init(&mnt->mnt_expire); | 684 | umount_tree(mnt); |
676 | spin_unlock(&vfsmount_lock); | 685 | spin_unlock(&vfsmount_lock); |
686 | } else | ||
687 | mntput(mnt); | ||
677 | 688 | ||
678 | err = graft_tree(mnt, nd); | 689 | out: |
679 | if (err) { | ||
680 | spin_lock(&vfsmount_lock); | ||
681 | umount_tree(mnt); | ||
682 | spin_unlock(&vfsmount_lock); | ||
683 | } else | ||
684 | mntput(mnt); | ||
685 | } | ||
686 | |||
687 | up_write(¤t->namespace->sem); | 690 | up_write(¤t->namespace->sem); |
688 | path_release(&old_nd); | 691 | path_release(&old_nd); |
689 | return err; | 692 | return err; |