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@xxxxxxxxxx> Signed-off-by: Al Viro <viro@xxxxxxxxxxxxxxxxxx> --- fs/namespace.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index d57e727962da..b236536bbbc9 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -3657,10 +3657,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; @@ -3674,14 +3677,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); @@ -3711,14 +3715,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; } @@ -3824,11 +3823,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; -- 2.47.2