summaryrefslogtreecommitdiff
path: root/fs/namespace.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2025-08-19 21:21:24 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2025-09-15 21:26:05 -0400
commitef307f89bfb662109a25acdde5b5837fe84a3a64 (patch)
tree6c05cbcfad15d6c9af70fadd89a15cf33bfc9565 /fs/namespace.c
parent842e12352c3074b8af1bc95cc2bb1e9fb47f4334 (diff)
do_add_mount(): switch to passing pinned_mountpoint instead of mountpoint + path
Both callers pass it a mountpoint reference picked from pinned_mountpoint and path it corresponds to. First of all, path->dentry is equal to mp.mp->m_dentry. Furthermore, path->mnt is &mp.parent->mnt, making struct path contents redundant. Pass it the address of that pinned_mountpoint instead; what's more, if we teach it to treat ERR_PTR(error) in ->parent as "bail out with that error" we can simplify the callers even more - do_add_mount() will do the right thing even when called after lock_mount() failure. Reviewed-by: Christian Brauner <brauner@kernel.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c32
1 files changed, 15 insertions, 17 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index bae4be8c7192..059ad02d214a 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -3652,10 +3652,13 @@ static int do_move_mount_old(struct path *path, const char *old_name)
/*
* add a mount into a namespace's mount tree
*/
-static int do_add_mount(struct mount *newmnt, struct mountpoint *mp,
- const struct path *path, int mnt_flags)
+static int do_add_mount(struct mount *newmnt, const struct pinned_mountpoint *mp,
+ int mnt_flags)
{
- struct mount *parent = real_mount(path->mnt);
+ struct mount *parent = mp->parent;
+
+ if (IS_ERR(parent))
+ return PTR_ERR(parent);
mnt_flags &= ~MNT_INTERNAL_FLAGS;
@@ -3669,14 +3672,15 @@ static int do_add_mount(struct mount *newmnt, struct mountpoint *mp,
}
/* Refuse the same filesystem on the same mount point */
- if (path->mnt->mnt_sb == newmnt->mnt.mnt_sb && path_mounted(path))
+ if (parent->mnt.mnt_sb == newmnt->mnt.mnt_sb &&
+ parent->mnt.mnt_root == mp->mp->m_dentry)
return -EBUSY;
if (d_is_symlink(newmnt->mnt.mnt_root))
return -EINVAL;
newmnt->mnt.mnt_flags = mnt_flags;
- return graft_tree(newmnt, parent, mp);
+ return graft_tree(newmnt, parent, mp->mp);
}
static bool mount_too_revealing(const struct super_block *sb, int *new_mnt_flags);
@@ -3706,14 +3710,9 @@ static int do_new_mount_fc(struct fs_context *fc, struct path *mountpoint,
mnt_warn_timestamp_expiry(mountpoint, mnt);
LOCK_MOUNT(mp, mountpoint);
- if (IS_ERR(mp.parent)) {
- return PTR_ERR(mp.parent);
- } else {
- error = do_add_mount(real_mount(mnt), mp.mp,
- mountpoint, mnt_flags);
- if (!error)
- retain_and_null_ptr(mnt); // consumed on success
- }
+ error = do_add_mount(real_mount(mnt), &mp, mnt_flags);
+ if (!error)
+ retain_and_null_ptr(mnt); // consumed on success
return error;
}
@@ -3819,11 +3818,10 @@ int finish_automount(struct vfsmount *__m, const struct path *path)
* got", not "try to mount it on top".
*/
LOCK_MOUNT_EXACT(mp, path);
- if (IS_ERR(mp.parent))
- return mp.parent == ERR_PTR(-EBUSY) ? 0 : PTR_ERR(mp.parent);
+ if (mp.parent == ERR_PTR(-EBUSY))
+ return 0;
- err = do_add_mount(mnt, mp.mp, path,
- path->mnt->mnt_flags | MNT_SHRINKABLE);
+ err = do_add_mount(mnt, &mp, path->mnt->mnt_flags | MNT_SHRINKABLE);
if (likely(!err))
retain_and_null_ptr(m);
return err;