| @@ -70,6 +70,8 @@ static struct hlist_head *mount_hashtable __read_mostly; · 69 unmodified lines |
| 70 | 70 | static struct hlist_head *mountpoint_hashtable __read_mostly; |
| 71 | 71 | static struct kmem_cache *mnt_cache __read_mostly; |
| 72 | 72 | static DECLARE_RWSEM(namespace_sem); |
| 73 | +static HLIST_HEAD(unmounted); /* protected by namespace_sem */ |
| 74 | +static LIST_HEAD(ex_mountpoints); /* protected by namespace_sem */ |
| 73 | 75 | |
| 74 | 76 | /* /sys/fs */ |
| 75 | 77 | struct kobject *fs_kobj; |
| @@ -170,14 +172,6 @@ unsigned int mnt_get_count(struct mount *mnt) · 94 unmodified lines |
| 170 | 172 | #endif |
| 171 | 173 | } |
| 172 | 174 | |
| 173 | | −static void drop_mountpoint(struct fs_pin *p) |
| 174 | | −{ |
| 175 | | − struct mount *m = container_of(p, struct mount, mnt_umount); |
| 176 | | − dput(m->mnt_ex_mountpoint); |
| 177 | | − pin_remove(p); |
| 178 | | − mntput(&m->mnt); |
| 179 | | −} |
| 180 | | − |
| 181 | 175 | static struct mount *alloc_vfsmnt(const char *name) |
| 182 | 176 | { |
| 183 | 177 | struct mount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); |
| @@ -215,7 +209,7 @@ static struct mount *alloc_vfsmnt(const char *name) · 31 unmodified lines |
| 215 | 209 | INIT_LIST_HEAD(&mnt->mnt_slave); |
| 216 | 210 | INIT_HLIST_NODE(&mnt->mnt_mp_list); |
| 217 | 211 | INIT_LIST_HEAD(&mnt->mnt_umounting); |
| 218 | | − init_fs_pin(&mnt->mnt_umount, drop_mountpoint); |
| 212 | + INIT_HLIST_HEAD(&mnt->mnt_stuck_children); |
| 219 | 213 | } |
| 220 | 214 | return mnt; |
| 221 | 215 | |
| @@ -740,7 +734,7 @@ mountpoint: · 518 unmodified lines |
| 740 | 734 | |
| 741 | 735 | /* Add the new mountpoint to the hash table */ |
| 742 | 736 | read_seqlock_excl(&mount_lock); |
| 743 | | − new->m_dentry = dentry; |
| 737 | + new->m_dentry = dget(dentry); |
| 744 | 738 | new->m_count = 1; |
| 745 | 739 | hlist_add_head(&new->m_hash, mp_hash(dentry)); |
| 746 | 740 | INIT_HLIST_HEAD(&new->m_list); |
| @@ -753,7 +747,11 @@ done: · 6 unmodified lines |
| 753 | 747 | return mp; |
| 754 | 748 | } |
| 755 | 749 | |
| 756 | | −static void put_mountpoint(struct mountpoint *mp) |
| 750 | +/* |
| 751 | + * vfsmount lock must be held. Additionally, the caller is responsible |
| 752 | + * for serializing calls for given disposal list. |
| 753 | + */ |
| 754 | +static void __put_mountpoint(struct mountpoint *mp, struct list_head *list) |
| 757 | 755 | { |
| 758 | 756 | if (!--mp->m_count) { |
| 759 | 757 | struct dentry *dentry = mp->m_dentry; |
| @@ -761,11 +759,18 @@ static void put_mountpoint(struct mountpoint *mp) · 1 unmodified line |
| 761 | 759 | spin_lock(&dentry->d_lock); |
| 762 | 760 | dentry->d_flags &= ~DCACHE_MOUNTED; |
| 763 | 761 | spin_unlock(&dentry->d_lock); |
| 762 | + dput_to_list(dentry, list); |
| 764 | 763 | hlist_del(&mp->m_hash); |
| 765 | 764 | kfree(mp); |
| 766 | 765 | } |
| 767 | 766 | } |
| 768 | 767 | |
| 768 | +/* called with namespace_lock and vfsmount lock */ |
| 769 | +static void put_mountpoint(struct mountpoint *mp) |
| 770 | +{ |
| 771 | + __put_mountpoint(mp, &ex_mountpoints); |
| 772 | +} |
| 773 | + |
| 769 | 774 | static inline int check_mnt(struct mount *mnt) |
| 770 | 775 | { |
| 771 | 776 | return mnt->mnt_ns == current->nsproxy->mnt_ns; |
| @@ -796,25 +801,17 @@ static void __touch_mnt_namespace(struct mnt_namespace *ns) · 24 unmodified lines |
| 796 | 801 | /* |
| 797 | 802 | * vfsmount lock must be held for write |
| 798 | 803 | */ |
| 799 | | −static void unhash_mnt(struct mount *mnt) |
| 804 | +static struct mountpoint *unhash_mnt(struct mount *mnt) |
| 800 | 805 | { |
| 806 | + struct mountpoint *mp; |
| 801 | 807 | mnt->mnt_parent = mnt; |
| 802 | 808 | mnt->mnt_mountpoint = mnt->mnt.mnt_root; |
| 803 | 809 | list_del_init(&mnt->mnt_child); |
| 804 | 810 | hlist_del_init_rcu(&mnt->mnt_hash); |
| 805 | 811 | hlist_del_init(&mnt->mnt_mp_list); |
| 806 | | − put_mountpoint(mnt->mnt_mp); |
| 812 | + mp = mnt->mnt_mp; |
| 807 | 813 | mnt->mnt_mp = NULL; |
| 808 | | −} |
| 809 | | − |
| 810 | | −/* |
| 811 | | − * vfsmount lock must be held for write |
| 812 | | − */ |
| 813 | | −static void detach_mnt(struct mount *mnt, struct path *old_path) |
| 814 | | −{ |
| 815 | | − old_path->dentry = mnt->mnt_mountpoint; |
| 816 | | − old_path->mnt = &mnt->mnt_parent->mnt; |
| 817 | | − unhash_mnt(mnt); |
| 814 | + return mp; |
| 818 | 815 | } |
| 819 | 816 | |
| 820 | 817 | /* |
| @@ -822,9 +819,7 @@ static void detach_mnt(struct mount *mnt, struct path *old_path) · 1 unmodified line |
| 822 | 819 | */ |
| 823 | 820 | static void umount_mnt(struct mount *mnt) |
| 824 | 821 | { |
| 825 | | − /* old mountpoint will be dropped when we can do that */ |
| 826 | | − mnt->mnt_ex_mountpoint = mnt->mnt_mountpoint; |
| 827 | | − unhash_mnt(mnt); |
| 822 | + put_mountpoint(unhash_mnt(mnt)); |
| 828 | 823 | } |
| 829 | 824 | |
| 830 | 825 | /* |
| @@ -836,7 +831,7 @@ void mnt_set_mountpoint(struct mount *mnt, · 5 unmodified lines |
| 836 | 831 | { |
| 837 | 832 | mp->m_count++; |
| 838 | 833 | mnt_add_count(mnt, 1); /* essentially, that's mntget */ |
| 839 | | − child_mnt->mnt_mountpoint = dget(mp->m_dentry); |
| 834 | + child_mnt->mnt_mountpoint = mp->m_dentry; |
| 840 | 835 | child_mnt->mnt_parent = mnt; |
| 841 | 836 | child_mnt->mnt_mp = mp; |
| 842 | 837 | hlist_add_head(&child_mnt->mnt_mp_list, &mp->m_list); |
| @@ -863,7 +858,6 @@ static void attach_mnt(struct mount *mnt, · 20 unmodified lines |
| 863 | 858 | void mnt_change_mountpoint(struct mount *parent, struct mountpoint *mp, struct mount *mnt) |
| 864 | 859 | { |
| 865 | 860 | struct mountpoint *old_mp = mnt->mnt_mp; |
| 866 | | − struct dentry *old_mountpoint = mnt->mnt_mountpoint; |
| 867 | 861 | struct mount *old_parent = mnt->mnt_parent; |
| 868 | 862 | |
| 869 | 863 | list_del_init(&mnt->mnt_child); |
| @@ -873,22 +867,6 @@ void mnt_change_mountpoint(struct mount *parent, struct mountpoint *mp, struct m · 3 unmodified lines |
| 873 | 867 | attach_mnt(mnt, parent, mp); |
| 874 | 868 | |
| 875 | 869 | put_mountpoint(old_mp); |
| 876 | | − |
| 877 | | − /* |
| 878 | | − * Safely avoid even the suggestion this code might sleep or |
| 879 | | − * lock the mount hash by taking advantage of the knowledge that |
| 880 | | − * mnt_change_mountpoint will not release the final reference |
| 881 | | − * to a mountpoint. |
| 882 | | − * |
| 883 | | − * During mounting, the mount passed in as the parent mount will |
| 884 | | − * continue to use the old mountpoint and during unmounting, the |
| 885 | | − * old mountpoint will continue to exist until namespace_unlock, |
| 886 | | − * which happens well after mnt_change_mountpoint. |
| 887 | | − */ |
| 888 | | − spin_lock(&old_mountpoint->d_lock); |
| 889 | | − old_mountpoint->d_lockref.count--; |
| 890 | | − spin_unlock(&old_mountpoint->d_lock); |
| 891 | | − |
| 892 | 870 | mnt_add_count(old_parent, -1); |
| 893 | 871 | } |
| 894 | 872 | |
| @@ -1103,19 +1081,22 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, · 208 unmodified lines |
| 1103 | 1081 | |
| 1104 | 1082 | static void cleanup_mnt(struct mount *mnt) |
| 1105 | 1083 | { |
| 1084 | + struct hlist_node *p; |
| 1085 | + struct mount *m; |
| 1106 | 1086 | /* |
| 1107 | | − * This probably indicates that somebody messed |
| 1108 | | − * up a mnt_want/drop_write() pair. If this |
| 1109 | | − * happens, the filesystem was probably unable |
| 1110 | | − * to make r/w->r/o transitions. |
| 1111 | | − */ |
| 1112 | | − /* |
| 1087 | + * The warning here probably indicates that somebody messed |
| 1088 | + * up a mnt_want/drop_write() pair. If this happens, the |
| 1089 | + * filesystem was probably unable to make r/w->r/o transitions. |
| 1113 | 1090 | * The locking used to deal with mnt_count decrement provides barriers, |
| 1114 | 1091 | * so mnt_get_writers() below is safe. |
| 1115 | 1092 | */ |
| 1116 | 1093 | WARN_ON(mnt_get_writers(mnt)); |
| 1117 | 1094 | if (unlikely(mnt->mnt_pins.first)) |
| 1118 | 1095 | mnt_pin_kill(mnt); |
| 1096 | + hlist_for_each_entry_safe(m, p, &mnt->mnt_stuck_children, mnt_umount) { |
| 1097 | + hlist_del(&m->mnt_umount); |
| 1098 | + mntput(&m->mnt); |
| 1099 | + } |
| 1119 | 1100 | fsnotify_vfsmount_delete(&mnt->mnt); |
| 1120 | 1101 | dput(mnt->mnt.mnt_root); |
| 1121 | 1102 | deactivate_super(mnt->mnt.mnt_sb); |
| @@ -1141,6 +1122,8 @@ static DECLARE_DELAYED_WORK(delayed_mntput_work, delayed_mntput); · 19 unmodified lines |
| 1141 | 1122 | |
| 1142 | 1123 | static void mntput_no_expire(struct mount *mnt) |
| 1143 | 1124 | { |
| 1125 | + LIST_HEAD(list); |
| 1126 | + |
| 1144 | 1127 | rcu_read_lock(); |
| 1145 | 1128 | if (likely(READ_ONCE(mnt->mnt_ns))) { |
| 1146 | 1129 | /* |
| @@ -1181,10 +1164,12 @@ static void mntput_no_expire(struct mount *mnt) · 34 unmodified lines |
| 1181 | 1164 | if (unlikely(!list_empty(&mnt->mnt_mounts))) { |
| 1182 | 1165 | struct mount *p, *tmp; |
| 1183 | 1166 | list_for_each_entry_safe(p, tmp, &mnt->mnt_mounts, mnt_child) { |
| 1184 | | − umount_mnt(p); |
| 1167 | + __put_mountpoint(unhash_mnt(p), &list); |
| 1168 | + hlist_add_head(&p->mnt_umount, &mnt->mnt_stuck_children); |
| 1185 | 1169 | } |
| 1186 | 1170 | } |
| 1187 | 1171 | unlock_mount_hash(); |
| 1172 | + shrink_dentry_list(&list); |
| 1188 | 1173 | |
| 1189 | 1174 | if (likely(!(mnt->mnt.mnt_flags & MNT_INTERNAL))) { |
| 1190 | 1175 | struct task_struct *task = current; |
| @@ -1370,22 +1355,29 @@ int may_umount(struct vfsmount *mnt) · 179 unmodified lines |
| 1370 | 1355 | |
| 1371 | 1356 | EXPORT_SYMBOL(may_umount); |
| 1372 | 1357 | |
| 1373 | | −static HLIST_HEAD(unmounted); /* protected by namespace_sem */ |
| 1374 | | − |
| 1375 | 1358 | static void namespace_unlock(void) |
| 1376 | 1359 | { |
| 1377 | 1360 | struct hlist_head head; |
| 1361 | + struct hlist_node *p; |
| 1362 | + struct mount *m; |
| 1363 | + LIST_HEAD(list); |
| 1378 | 1364 | |
| 1379 | 1365 | hlist_move_list(&unmounted, &head); |
| 1366 | + list_splice_init(&ex_mountpoints, &list); |
| 1380 | 1367 | |
| 1381 | 1368 | up_write(&namespace_sem); |
| 1382 | 1369 | |
| 1370 | + shrink_dentry_list(&list); |
| 1371 | + |
| 1383 | 1372 | if (likely(hlist_empty(&head))) |
| 1384 | 1373 | return; |
| 1385 | 1374 | |
| 1386 | 1375 | synchronize_rcu_expedited(); |
| 1387 | 1376 | |
| 1388 | | − group_pin_kill(&head); |
| 1377 | + hlist_for_each_entry_safe(m, p, &head, mnt_umount) { |
| 1378 | + hlist_del(&m->mnt_umount); |
| 1379 | + mntput(&m->mnt); |
| 1380 | + } |
| 1389 | 1381 | } |
| 1390 | 1382 | |
| 1391 | 1383 | static inline void namespace_lock(void) |
| @@ -1472,8 +1464,6 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how) · 80 unmodified lines |
| 1472 | 1464 | |
| 1473 | 1465 | disconnect = disconnect_mount(p, how); |
| 1474 | 1466 | |
| 1475 | | − pin_insert_group(&p->mnt_umount, &p->mnt_parent->mnt, |
| 1476 | | − disconnect ? &unmounted : NULL); |
| 1477 | 1467 | if (mnt_has_parent(p)) { |
| 1478 | 1468 | mnt_add_count(p->mnt_parent, -1); |
| 1479 | 1469 | if (!disconnect) { |
| @@ -1481,6 +1471,7 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how) · 1 unmodified line |
| 1481 | 1471 | list_add_tail(&p->mnt_child, &p->mnt_parent->mnt_mounts); |
| 1482 | 1472 | } else { |
| 1483 | 1473 | umount_mnt(p); |
| 1474 | + hlist_add_head(&p->mnt_umount, &unmounted); |
| 1484 | 1475 | } |
| 1485 | 1476 | } |
| 1486 | 1477 | change_mnt_propagation(p, MS_PRIVATE); |
| @@ -1626,15 +1617,15 @@ void __detach_mounts(struct dentry *dentry) · 139 unmodified lines |
| 1626 | 1617 | namespace_lock(); |
| 1627 | 1618 | lock_mount_hash(); |
| 1628 | 1619 | mp = lookup_mountpoint(dentry); |
| 1629 | | − if (IS_ERR_OR_NULL(mp)) |
| 1620 | + if (!mp) |
| 1630 | 1621 | goto out_unlock; |
| 1631 | 1622 | |
| 1632 | 1623 | event++; |
| 1633 | 1624 | while (!hlist_empty(&mp->m_list)) { |
| 1634 | 1625 | mnt = hlist_entry(mp->m_list.first, struct mount, mnt_mp_list); |
| 1635 | 1626 | if (mnt->mnt.mnt_flags & MNT_UMOUNT) { |
| 1636 | | − hlist_add_head(&mnt->mnt_umount.s_list, &unmounted); |
| 1637 | 1627 | umount_mnt(mnt); |
| 1628 | + hlist_add_head(&mnt->mnt_umount, &unmounted); |
| 1638 | 1629 | } |
| 1639 | 1630 | else umount_tree(mnt, UMOUNT_CONNECTED); |
| 1640 | 1631 | } |
| @@ -2046,7 +2037,7 @@ int count_mounts(struct mnt_namespace *ns, struct mount *mnt) · 405 unmodified lines |
| 2046 | 2037 | static int attach_recursive_mnt(struct mount *source_mnt, |
| 2047 | 2038 | struct mount *dest_mnt, |
| 2048 | 2039 | struct mountpoint *dest_mp, |
| 2049 | | − struct path *parent_path) |
| 2040 | + bool moving) |
| 2050 | 2041 | { |
| 2051 | 2042 | struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns; |
| 2052 | 2043 | HLIST_HEAD(tree_list); |
| @@ -2064,7 +2055,7 @@ static int attach_recursive_mnt(struct mount *source_mnt, · 11 unmodified lines |
| 2064 | 2055 | return PTR_ERR(smp); |
| 2065 | 2056 | |
| 2066 | 2057 | /* Is there space to add these mounts to the mount namespace? */ |
| 2067 | | − if (!parent_path) { |
| 2058 | + if (!moving) { |
| 2068 | 2059 | err = count_mounts(ns, source_mnt); |
| 2069 | 2060 | if (err) |
| 2070 | 2061 | goto out; |
| @@ -2083,8 +2074,8 @@ static int attach_recursive_mnt(struct mount *source_mnt, · 12 unmodified lines |
| 2083 | 2074 | } else { |
| 2084 | 2075 | lock_mount_hash(); |
| 2085 | 2076 | } |
| 2086 | | − if (parent_path) { |
| 2087 | | − detach_mnt(source_mnt, parent_path); |
| 2077 | + if (moving) { |
| 2078 | + unhash_mnt(source_mnt); |
| 2088 | 2079 | attach_mnt(source_mnt, dest_mnt, dest_mp); |
| 2089 | 2080 | touch_mnt_namespace(source_mnt->mnt_ns); |
| 2090 | 2081 | } else { |
| @@ -2182,7 +2173,7 @@ static int graft_tree(struct mount *mnt, struct mount *p, struct mountpoint *mp) · 91 unmodified lines |
| 2182 | 2173 | d_is_dir(mnt->mnt.mnt_root)) |
| 2183 | 2174 | return -ENOTDIR; |
| 2184 | 2175 | |
| 2185 | | − return attach_recursive_mnt(mnt, p, mp, NULL); |
| 2176 | + return attach_recursive_mnt(mnt, p, mp, false); |
| 2186 | 2177 | } |
| 2187 | 2178 | |
| 2188 | 2179 | /* |
| @@ -2575,11 +2566,11 @@ out: · 386 unmodified lines |
| 2575 | 2566 | |
| 2576 | 2567 | static int do_move_mount(struct path *old_path, struct path *new_path) |
| 2577 | 2568 | { |
| 2578 | | − struct path parent_path = {.mnt = NULL, .dentry = NULL}; |
| 2579 | 2569 | struct mnt_namespace *ns; |
| 2580 | 2570 | struct mount *p; |
| 2581 | 2571 | struct mount *old; |
| 2582 | | − struct mountpoint *mp; |
| 2572 | + struct mount *parent; |
| 2573 | + struct mountpoint *mp, *old_mp; |
| 2583 | 2574 | int err; |
| 2584 | 2575 | bool attached; |
| 2585 | 2576 | |
| @@ -2589,7 +2580,9 @@ static int do_move_mount(struct path *old_path, struct path *new_path) · 3 unmodified lines |
| 2589 | 2580 | |
| 2590 | 2581 | old = real_mount(old_path->mnt); |
| 2591 | 2582 | p = real_mount(new_path->mnt); |
| 2583 | + parent = old->mnt_parent; |
| 2592 | 2584 | attached = mnt_has_parent(old); |
| 2585 | + old_mp = old->mnt_mp; |
| 2593 | 2586 | ns = old->mnt_ns; |
| 2594 | 2587 | |
| 2595 | 2588 | err = -EINVAL; |
| @@ -2617,7 +2610,7 @@ static int do_move_mount(struct path *old_path, struct path *new_path) · 21 unmodified lines |
| 2617 | 2610 | /* |
| 2618 | 2611 | * Don't move a mount residing in a shared parent. |
| 2619 | 2612 | */ |
| 2620 | | − if (attached && IS_MNT_SHARED(old->mnt_parent)) |
| 2613 | + if (attached && IS_MNT_SHARED(parent)) |
| 2621 | 2614 | goto out; |
| 2622 | 2615 | /* |
| 2623 | 2616 | * Don't move a mount tree containing unbindable mounts to a destination |
| @@ -2633,18 +2626,21 @@ static int do_move_mount(struct path *old_path, struct path *new_path) · 9 unmodified lines |
| 2633 | 2626 | goto out; |
| 2634 | 2627 | |
| 2635 | 2628 | err = attach_recursive_mnt(old, real_mount(new_path->mnt), mp, |
| 2636 | | − attached ? &parent_path : NULL); |
| 2629 | + attached); |
| 2637 | 2630 | if (err) |
| 2638 | 2631 | goto out; |
| 2639 | 2632 | |
| 2640 | 2633 | /* if the mount is moved, it should no longer be expire |
| 2641 | 2634 | * automatically */ |
| 2642 | 2635 | list_del_init(&old->mnt_expire); |
| 2636 | + if (attached) |
| 2637 | + put_mountpoint(old_mp); |
| 2643 | 2638 | out: |
| 2644 | 2639 | unlock_mount(mp); |
| 2645 | 2640 | if (!err) { |
| 2646 | | − path_put(&parent_path); |
| 2647 | | − if (!attached) |
| 2641 | + if (attached) |
| 2642 | + mntput_no_expire(parent); |
| 2643 | + else |
| 2648 | 2644 | free_mnt_ns(ns); |
| 2649 | 2645 | } |
| 2650 | 2646 | return err; |
| @@ -3589,8 +3585,8 @@ EXPORT_SYMBOL(path_is_under); · 938 unmodified lines |
| 3589 | 3585 | SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, |
| 3590 | 3586 | const char __user *, put_old) |
| 3591 | 3587 | { |
| 3592 | | − struct path new, old, parent_path, root_parent, root; |
| 3593 | | − struct mount *new_mnt, *root_mnt, *old_mnt; |
| 3588 | + struct path new, old, root; |
| 3589 | + struct mount *new_mnt, *root_mnt, *old_mnt, *root_parent, *ex_parent; |
| 3594 | 3590 | struct mountpoint *old_mp, *root_mp; |
| 3595 | 3591 | int error; |
| 3596 | 3592 | |
| @@ -3619,9 +3615,11 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, · 22 unmodified lines |
| 3619 | 3615 | new_mnt = real_mount(new.mnt); |
| 3620 | 3616 | root_mnt = real_mount(root.mnt); |
| 3621 | 3617 | old_mnt = real_mount(old.mnt); |
| 3618 | + ex_parent = new_mnt->mnt_parent; |
| 3619 | + root_parent = root_mnt->mnt_parent; |
| 3622 | 3620 | if (IS_MNT_SHARED(old_mnt) || |
| 3623 | | − IS_MNT_SHARED(new_mnt->mnt_parent) || |
| 3624 | | − IS_MNT_SHARED(root_mnt->mnt_parent)) |
| 3621 | + IS_MNT_SHARED(ex_parent) || |
| 3622 | + IS_MNT_SHARED(root_parent)) |
| 3625 | 3623 | goto out4; |
| 3626 | 3624 | if (!check_mnt(root_mnt) || !check_mnt(new_mnt)) |
| 3627 | 3625 | goto out4; |
| @@ -3638,7 +3636,6 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, · 10 unmodified lines |
| 3638 | 3636 | goto out4; /* not a mountpoint */ |
| 3639 | 3637 | if (!mnt_has_parent(root_mnt)) |
| 3640 | 3638 | goto out4; /* not attached */ |
| 3641 | | − root_mp = root_mnt->mnt_mp; |
| 3642 | 3639 | if (new.mnt->mnt_root != new.dentry) |
| 3643 | 3640 | goto out4; /* not a mountpoint */ |
| 3644 | 3641 | if (!mnt_has_parent(new_mnt)) |
| @@ -3649,10 +3646,9 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, · 4 unmodified lines |
| 3649 | 3646 | /* make certain new is below the root */ |
| 3650 | 3647 | if (!is_path_reachable(new_mnt, new.dentry, &root)) |
| 3651 | 3648 | goto out4; |
| 3652 | | − root_mp->m_count++; /* pin it so it won't go away */ |
| 3653 | 3649 | lock_mount_hash(); |
| 3654 | | − detach_mnt(new_mnt, &parent_path); |
| 3655 | | − detach_mnt(root_mnt, &root_parent); |
| 3650 | + umount_mnt(new_mnt); |
| 3651 | + root_mp = unhash_mnt(root_mnt); /* we'll need its mountpoint */ |
| 3656 | 3652 | if (root_mnt->mnt.mnt_flags & MNT_LOCKED) { |
| 3657 | 3653 | new_mnt->mnt.mnt_flags |= MNT_LOCKED; |
| 3658 | 3654 | root_mnt->mnt.mnt_flags &= ~MNT_LOCKED; |
| @@ -3660,7 +3656,8 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, · 1 unmodified line |
| 3660 | 3656 | /* mount old root on put_old */ |
| 3661 | 3657 | attach_mnt(root_mnt, old_mnt, old_mp); |
| 3662 | 3658 | /* mount new_root on / */ |
| 3663 | | − attach_mnt(new_mnt, real_mount(root_parent.mnt), root_mp); |
| 3659 | + attach_mnt(new_mnt, root_parent, root_mp); |
| 3660 | + mnt_add_count(root_parent, -1); |
| 3664 | 3661 | touch_mnt_namespace(current->nsproxy->mnt_ns); |
| 3665 | 3662 | /* A moved mount should not expire automatically */ |
| 3666 | 3663 | list_del_init(&new_mnt->mnt_expire); |
| @@ -3670,10 +3667,8 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, · 3 unmodified lines |
| 3670 | 3667 | error = 0; |
| 3671 | 3668 | out4: |
| 3672 | 3669 | unlock_mount(old_mp); |
| 3673 | | − if (!error) { |
| 3674 | | − path_put(&root_parent); |
| 3675 | | − path_put(&parent_path); |
| 3676 | | − } |
| 3670 | + if (!error) |
| 3671 | + mntput_no_expire(ex_parent); |
| 3677 | 3672 | out3: |
| 3678 | 3673 | path_put(&root); |
| 3679 | 3674 | out2: |