[PATCH] cleanups and bug fix in do_loopback()
- check_mnt() on the source of binding should've been unconditional from the very beginning. My fault - as far I could've trace it, that's an old thinko made back in 2001. Kudos to Miklos for spotting it... Fixed. - code cleaned up. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
7b7b1ace2d
commit
ccd48bc7fa
1 changed files with 22 additions and 19 deletions
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue