get rid of detach_mnt()
authorAl Viro <viro@zeniv.linux.org.uk>
Sun, 30 Jun 2019 23:18:53 +0000 (19:18 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Wed, 17 Jul 2019 02:50:11 +0000 (22:50 -0400)
Lift getting the original mount (dentry is actually not needed at all)
of the mountpoint into the callers - to do_move_mount() and pivot_root()
level.  That simplifies the cleanup in those and allows to get saner
arguments for attach_mnt_recursive().

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/namespace.c

index e0902fd..46316ba 100644 (file)
@@ -823,16 +823,6 @@ static struct mountpoint *unhash_mnt(struct mount *mnt)
 /*
  * vfsmount lock must be held for write
  */
-static void detach_mnt(struct mount *mnt, struct path *old_path)
-{
-       old_path->dentry = dget(mnt->mnt_mountpoint);
-       old_path->mnt = &mnt->mnt_parent->mnt;
-       put_mountpoint(unhash_mnt(mnt));
-}
-
-/*
- * vfsmount lock must be held for write
- */
 static void umount_mnt(struct mount *mnt)
 {
        put_mountpoint(unhash_mnt(mnt));
@@ -2045,7 +2035,7 @@ int count_mounts(struct mnt_namespace *ns, struct mount *mnt)
 static int attach_recursive_mnt(struct mount *source_mnt,
                        struct mount *dest_mnt,
                        struct mountpoint *dest_mp,
-                       struct path *parent_path)
+                       bool moving)
 {
        struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns;
        HLIST_HEAD(tree_list);
@@ -2063,7 +2053,7 @@ static int attach_recursive_mnt(struct mount *source_mnt,
                return PTR_ERR(smp);
 
        /* Is there space to add these mounts to the mount namespace? */
-       if (!parent_path) {
+       if (!moving) {
                err = count_mounts(ns, source_mnt);
                if (err)
                        goto out;
@@ -2082,8 +2072,8 @@ static int attach_recursive_mnt(struct mount *source_mnt,
        } else {
                lock_mount_hash();
        }
-       if (parent_path) {
-               detach_mnt(source_mnt, parent_path);
+       if (moving) {
+               unhash_mnt(source_mnt);
                attach_mnt(source_mnt, dest_mnt, dest_mp);
                touch_mnt_namespace(source_mnt->mnt_ns);
        } else {
@@ -2181,7 +2171,7 @@ static int graft_tree(struct mount *mnt, struct mount *p, struct mountpoint *mp)
              d_is_dir(mnt->mnt.mnt_root))
                return -ENOTDIR;
 
-       return attach_recursive_mnt(mnt, p, mp, NULL);
+       return attach_recursive_mnt(mnt, p, mp, false);
 }
 
 /*
@@ -2574,11 +2564,11 @@ out:
 
 static int do_move_mount(struct path *old_path, struct path *new_path)
 {
-       struct path parent_path = {.mnt = NULL, .dentry = NULL};
        struct mnt_namespace *ns;
        struct mount *p;
        struct mount *old;
-       struct mountpoint *mp;
+       struct mount *parent;
+       struct mountpoint *mp, *old_mp;
        int err;
        bool attached;
 
@@ -2588,7 +2578,9 @@ static int do_move_mount(struct path *old_path, struct path *new_path)
 
        old = real_mount(old_path->mnt);
        p = real_mount(new_path->mnt);
+       parent = old->mnt_parent;
        attached = mnt_has_parent(old);
+       old_mp = old->mnt_mp;
        ns = old->mnt_ns;
 
        err = -EINVAL;
@@ -2616,7 +2608,7 @@ static int do_move_mount(struct path *old_path, struct path *new_path)
        /*
         * Don't move a mount residing in a shared parent.
         */
-       if (attached && IS_MNT_SHARED(old->mnt_parent))
+       if (attached && IS_MNT_SHARED(parent))
                goto out;
        /*
         * Don't move a mount tree containing unbindable mounts to a destination
@@ -2632,18 +2624,21 @@ static int do_move_mount(struct path *old_path, struct path *new_path)
                        goto out;
 
        err = attach_recursive_mnt(old, real_mount(new_path->mnt), mp,
-                                  attached ? &parent_path : NULL);
+                                  attached);
        if (err)
                goto out;
 
        /* if the mount is moved, it should no longer be expire
         * automatically */
        list_del_init(&old->mnt_expire);
+       if (attached)
+               put_mountpoint(old_mp);
 out:
        unlock_mount(mp);
        if (!err) {
-               path_put(&parent_path);
-               if (!attached)
+               if (attached)
+                       mntput_no_expire(parent);
+               else
                        free_mnt_ns(ns);
        }
        return err;
@@ -3586,8 +3581,8 @@ EXPORT_SYMBOL(path_is_under);
 SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
                const char __user *, put_old)
 {
-       struct path new, old, parent_path, root_parent, root;
-       struct mount *new_mnt, *root_mnt, *old_mnt;
+       struct path new, old, root;
+       struct mount *new_mnt, *root_mnt, *old_mnt, *root_parent, *ex_parent;
        struct mountpoint *old_mp, *root_mp;
        int error;
 
@@ -3616,9 +3611,11 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
        new_mnt = real_mount(new.mnt);
        root_mnt = real_mount(root.mnt);
        old_mnt = real_mount(old.mnt);
+       ex_parent = new_mnt->mnt_parent;
+       root_parent = root_mnt->mnt_parent;
        if (IS_MNT_SHARED(old_mnt) ||
-               IS_MNT_SHARED(new_mnt->mnt_parent) ||
-               IS_MNT_SHARED(root_mnt->mnt_parent))
+               IS_MNT_SHARED(ex_parent) ||
+               IS_MNT_SHARED(root_parent))
                goto out4;
        if (!check_mnt(root_mnt) || !check_mnt(new_mnt))
                goto out4;
@@ -3635,7 +3632,6 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
                goto out4; /* not a mountpoint */
        if (!mnt_has_parent(root_mnt))
                goto out4; /* not attached */
-       root_mp = root_mnt->mnt_mp;
        if (new.mnt->mnt_root != new.dentry)
                goto out4; /* not a mountpoint */
        if (!mnt_has_parent(new_mnt))
@@ -3646,10 +3642,9 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
        /* make certain new is below the root */
        if (!is_path_reachable(new_mnt, new.dentry, &root))
                goto out4;
-       root_mp->m_count++; /* pin it so it won't go away */
        lock_mount_hash();
-       detach_mnt(new_mnt, &parent_path);
-       detach_mnt(root_mnt, &root_parent);
+       umount_mnt(new_mnt);
+       root_mp = unhash_mnt(root_mnt);  /* we'll need its mountpoint */
        if (root_mnt->mnt.mnt_flags & MNT_LOCKED) {
                new_mnt->mnt.mnt_flags |= MNT_LOCKED;
                root_mnt->mnt.mnt_flags &= ~MNT_LOCKED;
@@ -3657,7 +3652,8 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
        /* mount old root on put_old */
        attach_mnt(root_mnt, old_mnt, old_mp);
        /* mount new_root on / */
-       attach_mnt(new_mnt, real_mount(root_parent.mnt), root_mp);
+       attach_mnt(new_mnt, root_parent, root_mp);
+       mnt_add_count(root_parent, -1);
        touch_mnt_namespace(current->nsproxy->mnt_ns);
        /* A moved mount should not expire automatically */
        list_del_init(&new_mnt->mnt_expire);
@@ -3667,10 +3663,8 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
        error = 0;
 out4:
        unlock_mount(old_mp);
-       if (!error) {
-               path_put(&root_parent);
-               path_put(&parent_path);
-       }
+       if (!error)
+               mntput_no_expire(ex_parent);
 out3:
        path_put(&root);
 out2: