]> www.infradead.org Git - users/hch/misc.git/commitdiff
finish_automount(): take the lock_mount() analogue into a helper
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 22 Aug 2025 16:59:10 +0000 (12:59 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Tue, 2 Sep 2025 23:35:59 +0000 (19:35 -0400)
finish_automount() can't use lock_mount() - it treats finding something
already mounted as "quitely drop our mount and return 0", not as
"mount on top of whatever mounted there".  It's been open-coded;
let's take it into a helper similar to lock_mount().  "something's
already mounted" => -EBUSY, finish_automount() needs to distinguish
it from the normal case and it can't happen in other failure cases.

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

index 90b62ee882da06d542d79fc01188c01d618ceab1..6251ee15f5f65a41e3ede3e5b73b63880561da77 100644 (file)
@@ -3781,9 +3781,29 @@ static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
        return err;
 }
 
-int finish_automount(struct vfsmount *m, const struct path *path)
+static int lock_mount_exact(const struct path *path,
+                           struct pinned_mountpoint *mp)
 {
        struct dentry *dentry = path->dentry;
+       int err;
+
+       inode_lock(dentry->d_inode);
+       namespace_lock();
+       if (unlikely(cant_mount(dentry)))
+               err = -ENOENT;
+       else if (path_overmounted(path))
+               err = -EBUSY;
+       else
+               err = get_mountpoint(dentry, mp);
+       if (unlikely(err)) {
+               namespace_unlock();
+               inode_unlock(dentry->d_inode);
+       }
+       return err;
+}
+
+int finish_automount(struct vfsmount *m, const struct path *path)
+{
        struct pinned_mountpoint mp = {};
        struct mount *mnt;
        int err;
@@ -3805,20 +3825,11 @@ int finish_automount(struct vfsmount *m, const struct path *path)
         * that overmounts our mountpoint to be means "quitely drop what we've
         * got", not "try to mount it on top".
         */
-       inode_lock(dentry->d_inode);
-       namespace_lock();
-       if (unlikely(cant_mount(dentry))) {
-               err = -ENOENT;
-               goto discard_locked;
-       }
-       if (path_overmounted(path)) {
-               err = 0;
-               goto discard_locked;
+       err = lock_mount_exact(path, &mp);
+       if (unlikely(err)) {
+               mntput(m);
+               return err == -EBUSY ? 0 : err;
        }
-       err = get_mountpoint(dentry, &mp);
-       if (err)
-               goto discard_locked;
-
        err = do_add_mount(mnt, mp.mp, path,
                           path->mnt->mnt_flags | MNT_SHRINKABLE);
        unlock_mount(&mp);
@@ -3826,9 +3837,6 @@ int finish_automount(struct vfsmount *m, const struct path *path)
                goto discard;
        return 0;
 
-discard_locked:
-       namespace_unlock();
-       inode_unlock(dentry->d_inode);
 discard:
        mntput(m);
        return err;