[PATCH] cleanups and bug fix in do_loopback()
authorAl Viro <viro@zeniv.linux.org.uk>
Mon, 7 Nov 2005 22:15:04 +0000 (17:15 -0500)
committerLinus Torvalds <torvalds@g5.osdl.org>
Tue, 8 Nov 2005 02:18:09 +0000 (18:18 -0800)
 - 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>
fs/namespace.c

index 1d83302..611f777 100644 (file)
@@ -661,29 +661,32 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse)
 
        down_write(&current->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(&current->namespace->sem);
        path_release(&old_nd);
        return err;