aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2025-08-26 13:57:42 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2025-09-02 19:35:58 -0400
commit5423426a79dd4d4422750b063febed40f362afcc (patch)
tree8ce1660de9cdb5bc816f81b3681218d9386cf3d9
parent8281f98a68d3306b2e47e6bb00708525562ccfdf (diff)
downloadrandom-5423426a79dd4d4422750b063febed40f362afcc.tar.gz
switch do_new_mount_fc() to fc_mount()
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>
-rw-r--r--fs/namespace.c29
1 files changed, 12 insertions, 17 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 0474b3a93dbf28..9b575c9eee0bb9 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -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;
}
@@ -3789,8 +3786,6 @@ static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
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);
put_fs_context(fc);