diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2019-06-30 19:18:53 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2019-07-16 22:50:11 -0400 |
commit | 2763d11912317a12318135ca03e592bb6df65624 (patch) | |
tree | 1a6c87b01ca0debc003a888b2e4ded3c9c11daeb | |
parent | 4edbe133f851c9e3a2f2a1db367e826b01e72594 (diff) |
get rid of detach_mnt()
Lift getting the original mount (dentry is actually not needed at all)
of the mountpoint into the callers - to do_move_mount() and pivot_root()
level. That simplifies the cleanup in those and allows to get saner
arguments for attach_mnt_recursive().
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/namespace.c | 62 |
1 files changed, 28 insertions, 34 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index e0902fda6f07..46316ba15615 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -823,16 +823,6 @@ static struct mountpoint *unhash_mnt(struct mount *mnt) | |||
823 | /* | 823 | /* |
824 | * vfsmount lock must be held for write | 824 | * vfsmount lock must be held for write |
825 | */ | 825 | */ |
826 | static void detach_mnt(struct mount *mnt, struct path *old_path) | ||
827 | { | ||
828 | old_path->dentry = dget(mnt->mnt_mountpoint); | ||
829 | old_path->mnt = &mnt->mnt_parent->mnt; | ||
830 | put_mountpoint(unhash_mnt(mnt)); | ||
831 | } | ||
832 | |||
833 | /* | ||
834 | * vfsmount lock must be held for write | ||
835 | */ | ||
836 | static void umount_mnt(struct mount *mnt) | 826 | static void umount_mnt(struct mount *mnt) |
837 | { | 827 | { |
838 | put_mountpoint(unhash_mnt(mnt)); | 828 | put_mountpoint(unhash_mnt(mnt)); |
@@ -2045,7 +2035,7 @@ int count_mounts(struct mnt_namespace *ns, struct mount *mnt) | |||
2045 | static int attach_recursive_mnt(struct mount *source_mnt, | 2035 | static int attach_recursive_mnt(struct mount *source_mnt, |
2046 | struct mount *dest_mnt, | 2036 | struct mount *dest_mnt, |
2047 | struct mountpoint *dest_mp, | 2037 | struct mountpoint *dest_mp, |
2048 | struct path *parent_path) | 2038 | bool moving) |
2049 | { | 2039 | { |
2050 | struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns; | 2040 | struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns; |
2051 | HLIST_HEAD(tree_list); | 2041 | HLIST_HEAD(tree_list); |
@@ -2063,7 +2053,7 @@ static int attach_recursive_mnt(struct mount *source_mnt, | |||
2063 | return PTR_ERR(smp); | 2053 | return PTR_ERR(smp); |
2064 | 2054 | ||
2065 | /* Is there space to add these mounts to the mount namespace? */ | 2055 | /* Is there space to add these mounts to the mount namespace? */ |
2066 | if (!parent_path) { | 2056 | if (!moving) { |
2067 | err = count_mounts(ns, source_mnt); | 2057 | err = count_mounts(ns, source_mnt); |
2068 | if (err) | 2058 | if (err) |
2069 | goto out; | 2059 | goto out; |
@@ -2082,8 +2072,8 @@ static int attach_recursive_mnt(struct mount *source_mnt, | |||
2082 | } else { | 2072 | } else { |
2083 | lock_mount_hash(); | 2073 | lock_mount_hash(); |
2084 | } | 2074 | } |
2085 | if (parent_path) { | 2075 | if (moving) { |
2086 | detach_mnt(source_mnt, parent_path); | 2076 | unhash_mnt(source_mnt); |
2087 | attach_mnt(source_mnt, dest_mnt, dest_mp); | 2077 | attach_mnt(source_mnt, dest_mnt, dest_mp); |
2088 | touch_mnt_namespace(source_mnt->mnt_ns); | 2078 | touch_mnt_namespace(source_mnt->mnt_ns); |
2089 | } else { | 2079 | } else { |
@@ -2181,7 +2171,7 @@ static int graft_tree(struct mount *mnt, struct mount *p, struct mountpoint *mp) | |||
2181 | d_is_dir(mnt->mnt.mnt_root)) | 2171 | d_is_dir(mnt->mnt.mnt_root)) |
2182 | return -ENOTDIR; | 2172 | return -ENOTDIR; |
2183 | 2173 | ||
2184 | return attach_recursive_mnt(mnt, p, mp, NULL); | 2174 | return attach_recursive_mnt(mnt, p, mp, false); |
2185 | } | 2175 | } |
2186 | 2176 | ||
2187 | /* | 2177 | /* |
@@ -2574,11 +2564,11 @@ out: | |||
2574 | 2564 | ||
2575 | static int do_move_mount(struct path *old_path, struct path *new_path) | 2565 | static int do_move_mount(struct path *old_path, struct path *new_path) |
2576 | { | 2566 | { |
2577 | struct path parent_path = {.mnt = NULL, .dentry = NULL}; | ||
2578 | struct mnt_namespace *ns; | 2567 | struct mnt_namespace *ns; |
2579 | struct mount *p; | 2568 | struct mount *p; |
2580 | struct mount *old; | 2569 | struct mount *old; |
2581 | struct mountpoint *mp; | 2570 | struct mount *parent; |
2571 | struct mountpoint *mp, *old_mp; | ||
2582 | int err; | 2572 | int err; |
2583 | bool attached; | 2573 | bool attached; |
2584 | 2574 | ||
@@ -2588,7 +2578,9 @@ static int do_move_mount(struct path *old_path, struct path *new_path) | |||
2588 | 2578 | ||
2589 | old = real_mount(old_path->mnt); | 2579 | old = real_mount(old_path->mnt); |
2590 | p = real_mount(new_path->mnt); | 2580 | p = real_mount(new_path->mnt); |
2581 | parent = old->mnt_parent; | ||
2591 | attached = mnt_has_parent(old); | 2582 | attached = mnt_has_parent(old); |
2583 | old_mp = old->mnt_mp; | ||
2592 | ns = old->mnt_ns; | 2584 | ns = old->mnt_ns; |
2593 | 2585 | ||
2594 | err = -EINVAL; | 2586 | err = -EINVAL; |
@@ -2616,7 +2608,7 @@ static int do_move_mount(struct path *old_path, struct path *new_path) | |||
2616 | /* | 2608 | /* |
2617 | * Don't move a mount residing in a shared parent. | 2609 | * Don't move a mount residing in a shared parent. |
2618 | */ | 2610 | */ |
2619 | if (attached && IS_MNT_SHARED(old->mnt_parent)) | 2611 | if (attached && IS_MNT_SHARED(parent)) |
2620 | goto out; | 2612 | goto out; |
2621 | /* | 2613 | /* |
2622 | * Don't move a mount tree containing unbindable mounts to a destination | 2614 | * Don't move a mount tree containing unbindable mounts to a destination |
@@ -2632,18 +2624,21 @@ static int do_move_mount(struct path *old_path, struct path *new_path) | |||
2632 | goto out; | 2624 | goto out; |
2633 | 2625 | ||
2634 | err = attach_recursive_mnt(old, real_mount(new_path->mnt), mp, | 2626 | err = attach_recursive_mnt(old, real_mount(new_path->mnt), mp, |
2635 | attached ? &parent_path : NULL); | 2627 | attached); |
2636 | if (err) | 2628 | if (err) |
2637 | goto out; | 2629 | goto out; |
2638 | 2630 | ||
2639 | /* if the mount is moved, it should no longer be expire | 2631 | /* if the mount is moved, it should no longer be expire |
2640 | * automatically */ | 2632 | * automatically */ |
2641 | list_del_init(&old->mnt_expire); | 2633 | list_del_init(&old->mnt_expire); |
2634 | if (attached) | ||
2635 | put_mountpoint(old_mp); | ||
2642 | out: | 2636 | out: |
2643 | unlock_mount(mp); | 2637 | unlock_mount(mp); |
2644 | if (!err) { | 2638 | if (!err) { |
2645 | path_put(&parent_path); | 2639 | if (attached) |
2646 | if (!attached) | 2640 | mntput_no_expire(parent); |
2641 | else | ||
2647 | free_mnt_ns(ns); | 2642 | free_mnt_ns(ns); |
2648 | } | 2643 | } |
2649 | return err; | 2644 | return err; |
@@ -3586,8 +3581,8 @@ EXPORT_SYMBOL(path_is_under); | |||
3586 | SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, | 3581 | SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, |
3587 | const char __user *, put_old) | 3582 | const char __user *, put_old) |
3588 | { | 3583 | { |
3589 | struct path new, old, parent_path, root_parent, root; | 3584 | struct path new, old, root; |
3590 | struct mount *new_mnt, *root_mnt, *old_mnt; | 3585 | struct mount *new_mnt, *root_mnt, *old_mnt, *root_parent, *ex_parent; |
3591 | struct mountpoint *old_mp, *root_mp; | 3586 | struct mountpoint *old_mp, *root_mp; |
3592 | int error; | 3587 | int error; |
3593 | 3588 | ||
@@ -3616,9 +3611,11 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, | |||
3616 | new_mnt = real_mount(new.mnt); | 3611 | new_mnt = real_mount(new.mnt); |
3617 | root_mnt = real_mount(root.mnt); | 3612 | root_mnt = real_mount(root.mnt); |
3618 | old_mnt = real_mount(old.mnt); | 3613 | old_mnt = real_mount(old.mnt); |
3614 | ex_parent = new_mnt->mnt_parent; | ||
3615 | root_parent = root_mnt->mnt_parent; | ||
3619 | if (IS_MNT_SHARED(old_mnt) || | 3616 | if (IS_MNT_SHARED(old_mnt) || |
3620 | IS_MNT_SHARED(new_mnt->mnt_parent) || | 3617 | IS_MNT_SHARED(ex_parent) || |
3621 | IS_MNT_SHARED(root_mnt->mnt_parent)) | 3618 | IS_MNT_SHARED(root_parent)) |
3622 | goto out4; | 3619 | goto out4; |
3623 | if (!check_mnt(root_mnt) || !check_mnt(new_mnt)) | 3620 | if (!check_mnt(root_mnt) || !check_mnt(new_mnt)) |
3624 | goto out4; | 3621 | goto out4; |
@@ -3635,7 +3632,6 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, | |||
3635 | goto out4; /* not a mountpoint */ | 3632 | goto out4; /* not a mountpoint */ |
3636 | if (!mnt_has_parent(root_mnt)) | 3633 | if (!mnt_has_parent(root_mnt)) |
3637 | goto out4; /* not attached */ | 3634 | goto out4; /* not attached */ |
3638 | root_mp = root_mnt->mnt_mp; | ||
3639 | if (new.mnt->mnt_root != new.dentry) | 3635 | if (new.mnt->mnt_root != new.dentry) |
3640 | goto out4; /* not a mountpoint */ | 3636 | goto out4; /* not a mountpoint */ |
3641 | if (!mnt_has_parent(new_mnt)) | 3637 | if (!mnt_has_parent(new_mnt)) |
@@ -3646,10 +3642,9 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, | |||
3646 | /* make certain new is below the root */ | 3642 | /* make certain new is below the root */ |
3647 | if (!is_path_reachable(new_mnt, new.dentry, &root)) | 3643 | if (!is_path_reachable(new_mnt, new.dentry, &root)) |
3648 | goto out4; | 3644 | goto out4; |
3649 | root_mp->m_count++; /* pin it so it won't go away */ | ||
3650 | lock_mount_hash(); | 3645 | lock_mount_hash(); |
3651 | detach_mnt(new_mnt, &parent_path); | 3646 | umount_mnt(new_mnt); |
3652 | detach_mnt(root_mnt, &root_parent); | 3647 | root_mp = unhash_mnt(root_mnt); /* we'll need its mountpoint */ |
3653 | if (root_mnt->mnt.mnt_flags & MNT_LOCKED) { | 3648 | if (root_mnt->mnt.mnt_flags & MNT_LOCKED) { |
3654 | new_mnt->mnt.mnt_flags |= MNT_LOCKED; | 3649 | new_mnt->mnt.mnt_flags |= MNT_LOCKED; |
3655 | root_mnt->mnt.mnt_flags &= ~MNT_LOCKED; | 3650 | root_mnt->mnt.mnt_flags &= ~MNT_LOCKED; |
@@ -3657,7 +3652,8 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, | |||
3657 | /* mount old root on put_old */ | 3652 | /* mount old root on put_old */ |
3658 | attach_mnt(root_mnt, old_mnt, old_mp); | 3653 | attach_mnt(root_mnt, old_mnt, old_mp); |
3659 | /* mount new_root on / */ | 3654 | /* mount new_root on / */ |
3660 | attach_mnt(new_mnt, real_mount(root_parent.mnt), root_mp); | 3655 | attach_mnt(new_mnt, root_parent, root_mp); |
3656 | mnt_add_count(root_parent, -1); | ||
3661 | touch_mnt_namespace(current->nsproxy->mnt_ns); | 3657 | touch_mnt_namespace(current->nsproxy->mnt_ns); |
3662 | /* A moved mount should not expire automatically */ | 3658 | /* A moved mount should not expire automatically */ |
3663 | list_del_init(&new_mnt->mnt_expire); | 3659 | list_del_init(&new_mnt->mnt_expire); |
@@ -3667,10 +3663,8 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, | |||
3667 | error = 0; | 3663 | error = 0; |
3668 | out4: | 3664 | out4: |
3669 | unlock_mount(old_mp); | 3665 | unlock_mount(old_mp); |
3670 | if (!error) { | 3666 | if (!error) |
3671 | path_put(&root_parent); | 3667 | mntput_no_expire(ex_parent); |
3672 | path_put(&parent_path); | ||
3673 | } | ||
3674 | out3: | 3668 | out3: |
3675 | path_put(&root); | 3669 | path_put(&root); |
3676 | out2: | 3670 | out2: |