@@ -820,16 +820,6 @@ static struct mountpoint *unhash_mnt(struct mount *mnt)
820
820
return mp ;
821
821
}
822
822
823
- /*
824
- * vfsmount lock must be held for write
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
823
/*
834
824
* vfsmount lock must be held for write
835
825
*/
@@ -2045,7 +2035,7 @@ int count_mounts(struct mnt_namespace *ns, struct mount *mnt)
2045
2035
static int attach_recursive_mnt (struct mount * source_mnt ,
2046
2036
struct mount * dest_mnt ,
2047
2037
struct mountpoint * dest_mp ,
2048
- struct path * parent_path )
2038
+ bool moving )
2049
2039
{
2050
2040
struct user_namespace * user_ns = current -> nsproxy -> mnt_ns -> user_ns ;
2051
2041
HLIST_HEAD (tree_list );
@@ -2063,7 +2053,7 @@ static int attach_recursive_mnt(struct mount *source_mnt,
2063
2053
return PTR_ERR (smp );
2064
2054
2065
2055
/* Is there space to add these mounts to the mount namespace? */
2066
- if (!parent_path ) {
2056
+ if (!moving ) {
2067
2057
err = count_mounts (ns , source_mnt );
2068
2058
if (err )
2069
2059
goto out ;
@@ -2082,8 +2072,8 @@ static int attach_recursive_mnt(struct mount *source_mnt,
2082
2072
} else {
2083
2073
lock_mount_hash ();
2084
2074
}
2085
- if (parent_path ) {
2086
- detach_mnt (source_mnt , parent_path );
2075
+ if (moving ) {
2076
+ unhash_mnt (source_mnt );
2087
2077
attach_mnt (source_mnt , dest_mnt , dest_mp );
2088
2078
touch_mnt_namespace (source_mnt -> mnt_ns );
2089
2079
} else {
@@ -2181,7 +2171,7 @@ static int graft_tree(struct mount *mnt, struct mount *p, struct mountpoint *mp)
2181
2171
d_is_dir (mnt -> mnt .mnt_root ))
2182
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 @@ static bool check_for_nsfs_mounts(struct mount *subtree)
2574
2564
2575
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
2567
struct mnt_namespace * ns ;
2579
2568
struct mount * p ;
2580
2569
struct mount * old ;
2581
- struct mountpoint * mp ;
2570
+ struct mount * parent ;
2571
+ struct mountpoint * mp , * old_mp ;
2582
2572
int err ;
2583
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
2579
old = real_mount (old_path -> mnt );
2590
2580
p = real_mount (new_path -> mnt );
2581
+ parent = old -> mnt_parent ;
2591
2582
attached = mnt_has_parent (old );
2583
+ old_mp = old -> mnt_mp ;
2592
2584
ns = old -> mnt_ns ;
2593
2585
2594
2586
err = - EINVAL ;
@@ -2616,7 +2608,7 @@ static int do_move_mount(struct path *old_path, struct path *new_path)
2616
2608
/*
2617
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
2612
goto out ;
2621
2613
/*
2622
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
2624
goto out ;
2633
2625
2634
2626
err = attach_recursive_mnt (old , real_mount (new_path -> mnt ), mp ,
2635
- attached ? & parent_path : NULL );
2627
+ attached );
2636
2628
if (err )
2637
2629
goto out ;
2638
2630
2639
2631
/* if the mount is moved, it should no longer be expire
2640
2632
* automatically */
2641
2633
list_del_init (& old -> mnt_expire );
2634
+ if (attached )
2635
+ put_mountpoint (old_mp );
2642
2636
out :
2643
2637
unlock_mount (mp );
2644
2638
if (!err ) {
2645
- path_put (& parent_path );
2646
- if (!attached )
2639
+ if (attached )
2640
+ mntput_no_expire (parent );
2641
+ else
2647
2642
free_mnt_ns (ns );
2648
2643
}
2649
2644
return err ;
@@ -3586,8 +3581,8 @@ EXPORT_SYMBOL(path_is_under);
3586
3581
SYSCALL_DEFINE2 (pivot_root , const char __user * , new_root ,
3587
3582
const char __user * , put_old )
3588
3583
{
3589
- struct path new , old , parent_path , root_parent , root ;
3590
- struct mount * new_mnt , * root_mnt , * old_mnt ;
3584
+ struct path new , old , root ;
3585
+ struct mount * new_mnt , * root_mnt , * old_mnt , * root_parent , * ex_parent ;
3591
3586
struct mountpoint * old_mp , * root_mp ;
3592
3587
int error ;
3593
3588
@@ -3616,9 +3611,11 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
3616
3611
new_mnt = real_mount (new .mnt );
3617
3612
root_mnt = real_mount (root .mnt );
3618
3613
old_mnt = real_mount (old .mnt );
3614
+ ex_parent = new_mnt -> mnt_parent ;
3615
+ root_parent = root_mnt -> mnt_parent ;
3619
3616
if (IS_MNT_SHARED (old_mnt ) ||
3620
- IS_MNT_SHARED (new_mnt -> mnt_parent ) ||
3621
- IS_MNT_SHARED (root_mnt -> mnt_parent ))
3617
+ IS_MNT_SHARED (ex_parent ) ||
3618
+ IS_MNT_SHARED (root_parent ))
3622
3619
goto out4 ;
3623
3620
if (!check_mnt (root_mnt ) || !check_mnt (new_mnt ))
3624
3621
goto out4 ;
@@ -3635,7 +3632,6 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
3635
3632
goto out4 ; /* not a mountpoint */
3636
3633
if (!mnt_has_parent (root_mnt ))
3637
3634
goto out4 ; /* not attached */
3638
- root_mp = root_mnt -> mnt_mp ;
3639
3635
if (new .mnt -> mnt_root != new .dentry )
3640
3636
goto out4 ; /* not a mountpoint */
3641
3637
if (!mnt_has_parent (new_mnt ))
@@ -3646,18 +3642,18 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
3646
3642
/* make certain new is below the root */
3647
3643
if (!is_path_reachable (new_mnt , new .dentry , & root ))
3648
3644
goto out4 ;
3649
- root_mp -> m_count ++ ; /* pin it so it won't go away */
3650
3645
lock_mount_hash ();
3651
- detach_mnt (new_mnt , & parent_path );
3652
- detach_mnt (root_mnt , & root_parent );
3646
+ umount_mnt (new_mnt );
3647
+ root_mp = unhash_mnt (root_mnt ); /* we'll need its mountpoint */
3653
3648
if (root_mnt -> mnt .mnt_flags & MNT_LOCKED ) {
3654
3649
new_mnt -> mnt .mnt_flags |= MNT_LOCKED ;
3655
3650
root_mnt -> mnt .mnt_flags &= ~MNT_LOCKED ;
3656
3651
}
3657
3652
/* mount old root on put_old */
3658
3653
attach_mnt (root_mnt , old_mnt , old_mp );
3659
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
3657
touch_mnt_namespace (current -> nsproxy -> mnt_ns );
3662
3658
/* A moved mount should not expire automatically */
3663
3659
list_del_init (& new_mnt -> mnt_expire );
@@ -3667,10 +3663,8 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
3667
3663
error = 0 ;
3668
3664
out4 :
3669
3665
unlock_mount (old_mp );
3670
- if (!error ) {
3671
- path_put (& root_parent );
3672
- path_put (& parent_path );
3673
- }
3666
+ if (!error )
3667
+ mntput_no_expire (ex_parent );
3674
3668
out3 :
3675
3669
path_put (& root );
3676
3670
out2 :
0 commit comments