]> www.infradead.org Git - users/hch/misc.git/commitdiff
do_add_mount(): switch to passing pinned_mountpoint instead of mountpoint + path
authorAl Viro <viro@zeniv.linux.org.uk>
Wed, 20 Aug 2025 01:21:24 +0000 (21:21 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Tue, 16 Sep 2025 01:26:05 +0000 (21:26 -0400)
Both callers pass it a mountpoint reference picked from pinned_mountpoint
and path it corresponds to.

First of all, path->dentry is equal to mp.mp->m_dentry.  Furthermore, path->mnt
is &mp.parent->mnt, making struct path contents redundant.

Pass it the address of that pinned_mountpoint instead; what's more, if we
teach it to treat ERR_PTR(error) in ->parent as "bail out with that error"
we can simplify the callers even more - do_add_mount() will do the right
thing even when called after lock_mount() failure.

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

index bae4be8c7192a45bca8fb67d1b85c6101ff349db..059ad02d214affac42d131db4d0c265ca5282871 100644 (file)
@@ -3652,10 +3652,13 @@ static int do_move_mount_old(struct path *path, const char *old_name)
 /*
  * add a mount into a namespace's mount tree
  */
-static int do_add_mount(struct mount *newmnt, struct mountpoint *mp,
-                       const struct path *path, int mnt_flags)
+static int do_add_mount(struct mount *newmnt, const struct pinned_mountpoint *mp,
+                       int mnt_flags)
 {
-       struct mount *parent = real_mount(path->mnt);
+       struct mount *parent = mp->parent;
+
+       if (IS_ERR(parent))
+               return PTR_ERR(parent);
 
        mnt_flags &= ~MNT_INTERNAL_FLAGS;
 
@@ -3669,14 +3672,15 @@ static int do_add_mount(struct mount *newmnt, struct mountpoint *mp,
        }
 
        /* Refuse the same filesystem on the same mount point */
-       if (path->mnt->mnt_sb == newmnt->mnt.mnt_sb && path_mounted(path))
+       if (parent->mnt.mnt_sb == newmnt->mnt.mnt_sb &&
+           parent->mnt.mnt_root == mp->mp->m_dentry)
                return -EBUSY;
 
        if (d_is_symlink(newmnt->mnt.mnt_root))
                return -EINVAL;
 
        newmnt->mnt.mnt_flags = mnt_flags;
-       return graft_tree(newmnt, parent, mp);
+       return graft_tree(newmnt, parent, mp->mp);
 }
 
 static bool mount_too_revealing(const struct super_block *sb, int *new_mnt_flags);
@@ -3706,14 +3710,9 @@ static int do_new_mount_fc(struct fs_context *fc, struct path *mountpoint,
        mnt_warn_timestamp_expiry(mountpoint, mnt);
 
        LOCK_MOUNT(mp, mountpoint);
-       if (IS_ERR(mp.parent)) {
-               return PTR_ERR(mp.parent);
-       } else {
-               error = do_add_mount(real_mount(mnt), mp.mp,
-                                    mountpoint, mnt_flags);
-               if (!error)
-                       retain_and_null_ptr(mnt); // consumed on success
-       }
+       error = do_add_mount(real_mount(mnt), &mp, mnt_flags);
+       if (!error)
+               retain_and_null_ptr(mnt); // consumed on success
        return error;
 }
 
@@ -3819,11 +3818,10 @@ int finish_automount(struct vfsmount *__m, const struct path *path)
         * got", not "try to mount it on top".
         */
        LOCK_MOUNT_EXACT(mp, path);
-       if (IS_ERR(mp.parent))
-               return mp.parent == ERR_PTR(-EBUSY) ? 0 : PTR_ERR(mp.parent);
+       if (mp.parent == ERR_PTR(-EBUSY))
+               return 0;
 
-       err = do_add_mount(mnt, mp.mp, path,
-                          path->mnt->mnt_flags | MNT_SHRINKABLE);
+       err = do_add_mount(mnt, &mp, path->mnt->mnt_flags | MNT_SHRINKABLE);
        if (likely(!err))
                retain_and_null_ptr(m);
        return err;