diff options
Diffstat (limited to 'fs/namespace.c')
-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) down_write(¤t->namespace->sem); err = -EINVAL; - if (check_mnt(nd->mnt) && (!recurse || check_mnt(old_nd.mnt))) { - err = -ENOMEM; - if (recurse) - mnt = copy_tree(old_nd.mnt, old_nd.dentry); - else - mnt = clone_mnt(old_nd.mnt, old_nd.dentry); - } + if (!check_mnt(nd->mnt) || !check_mnt(old_nd.mnt)) + goto out; - if (mnt) { - /* stop bind mounts from expiring */ + err = -ENOMEM; + if (recurse) + mnt = copy_tree(old_nd.mnt, old_nd.dentry); + else + mnt = clone_mnt(old_nd.mnt, old_nd.dentry); + + if (!mnt) + goto out; + + /* stop bind mounts from expiring */ + spin_lock(&vfsmount_lock); + list_del_init(&mnt->mnt_expire); + spin_unlock(&vfsmount_lock); + + err = graft_tree(mnt, nd); + if (err) { spin_lock(&vfsmount_lock); - list_del_init(&mnt->mnt_expire); + umount_tree(mnt); spin_unlock(&vfsmount_lock); + } else + mntput(mnt); - err = graft_tree(mnt, nd); - if (err) { - spin_lock(&vfsmount_lock); - umount_tree(mnt); - spin_unlock(&vfsmount_lock); - } else - mntput(mnt); - } - +out: up_write(¤t->namespace->sem); path_release(&old_nd); return err; |