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 1d83302f30c..611f777bbd6 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; | 
