]> www.infradead.org Git - users/hch/misc.git/commitdiff
switch do_new_mount_fc() to fc_mount()
authorAl Viro <viro@zeniv.linux.org.uk>
Tue, 26 Aug 2025 17:57:42 +0000 (13:57 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Tue, 2 Sep 2025 23:35:58 +0000 (19:35 -0400)
Prior to the call of do_new_mount_fc() the caller has just done successful
vfs_get_tree().  Then do_new_mount_fc() does several checks on resulting
superblock, and either does fc_drop_locked() and returns an error or
proceeds to unlock the superblock and call vfs_create_mount().

The thing is, there's no reason to delay that unlock + vfs_create_mount() -
the tests do not rely upon the state of ->s_umount and
fc_drop_locked()
put_fs_context()
is equivalent to
unlock ->s_umount
put_fs_context()

Doing vfs_create_mount() before the checks allows us to move vfs_get_tree()
from caller to do_new_mount_fc() and collapse it with vfs_create_mount()
into an fc_mount() call.

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

index 0474b3a93dbf2859ae853cd156fad235b10190b3..9b575c9eee0bb956d8a50effa387a77dc0281f5f 100644 (file)
@@ -3705,25 +3705,20 @@ static bool mount_too_revealing(const struct super_block *sb, int *new_mnt_flags
 static int do_new_mount_fc(struct fs_context *fc, struct path *mountpoint,
                           unsigned int mnt_flags)
 {
-       struct vfsmount *mnt;
        struct pinned_mountpoint mp = {};
-       struct super_block *sb = fc->root->d_sb;
+       struct super_block *sb;
+       struct vfsmount *mnt = fc_mount(fc);
        int error;
 
+       if (IS_ERR(mnt))
+               return PTR_ERR(mnt);
+
+       sb = fc->root->d_sb;
        error = security_sb_kern_mount(sb);
        if (!error && mount_too_revealing(sb, &mnt_flags))
                error = -EPERM;
-
-       if (unlikely(error)) {
-               fc_drop_locked(fc);
-               return error;
-       }
-
-       up_write(&sb->s_umount);
-
-       mnt = vfs_create_mount(fc);
-       if (IS_ERR(mnt))
-               return PTR_ERR(mnt);
+       if (unlikely(error))
+               goto out;
 
        mnt_warn_timestamp_expiry(mountpoint, mnt);
 
@@ -3731,10 +3726,12 @@ static int do_new_mount_fc(struct fs_context *fc, struct path *mountpoint,
        if (!error) {
                error = do_add_mount(real_mount(mnt), mp.mp,
                                     mountpoint, mnt_flags);
+               if (!error)
+                       mnt = NULL;     // consumed on success
                unlock_mount(&mp);
        }
-       if (error < 0)
-               mntput(mnt);
+out:
+       mntput(mnt);
        return error;
 }
 
@@ -3788,8 +3785,6 @@ static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
                err = parse_monolithic_mount_data(fc, data);
        if (!err && !mount_capable(fc))
                err = -EPERM;
-       if (!err)
-               err = vfs_get_tree(fc);
        if (!err)
                err = do_new_mount_fc(fc, path, mnt_flags);