Re: [PATCH 24/52] finish_automount(): take the lock_mount() analogue into a helper

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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);




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux