On Mon, Aug 25, 2025 at 05:43:27AM +0100, Al Viro wrote: > 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. > > Signed-off-by: Al Viro <viro@xxxxxxxxxxxxxxxxxx> > --- Reviewed-by: Christian Brauner <brauner@xxxxxxxxxx> > fs/namespace.c | 42 +++++++++++++++++++++++++----------------- > 1 file changed, 25 insertions(+), 17 deletions(-) > > diff --git a/fs/namespace.c b/fs/namespace.c > index 892251663419..99757040a39a 100644 > --- a/fs/namespace.c > +++ b/fs/namespace.c > @@ -3786,9 +3786,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; > @@ -3810,20 +3830,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); > @@ -3831,9 +3842,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); Can use direct returns if you do: struct mount *mnt __free(mntput) = NULL; and then in the success condition: retain_and_null_ptr(mnt);