|
@@ -1099,6 +1099,13 @@ static void mntput_no_expire(struct mount *mnt)
|
|
|
rcu_read_unlock();
|
|
|
|
|
|
list_del(&mnt->mnt_instance);
|
|
|
+
|
|
|
+ if (unlikely(!list_empty(&mnt->mnt_mounts))) {
|
|
|
+ struct mount *p, *tmp;
|
|
|
+ list_for_each_entry_safe(p, tmp, &mnt->mnt_mounts, mnt_child) {
|
|
|
+ umount_mnt(p);
|
|
|
+ }
|
|
|
+ }
|
|
|
unlock_mount_hash();
|
|
|
|
|
|
if (likely(!(mnt->mnt.mnt_flags & MNT_INTERNAL))) {
|
|
@@ -1370,6 +1377,7 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how)
|
|
|
propagate_umount(&tmp_list);
|
|
|
|
|
|
while (!list_empty(&tmp_list)) {
|
|
|
+ bool disconnect;
|
|
|
p = list_first_entry(&tmp_list, struct mount, mnt_list);
|
|
|
list_del_init(&p->mnt_expire);
|
|
|
list_del_init(&p->mnt_list);
|
|
@@ -1378,10 +1386,18 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how)
|
|
|
if (how & UMOUNT_SYNC)
|
|
|
p->mnt.mnt_flags |= MNT_SYNC_UMOUNT;
|
|
|
|
|
|
- pin_insert_group(&p->mnt_umount, &p->mnt_parent->mnt, &unmounted);
|
|
|
+ disconnect = !IS_MNT_LOCKED_AND_LAZY(p);
|
|
|
+
|
|
|
+ pin_insert_group(&p->mnt_umount, &p->mnt_parent->mnt,
|
|
|
+ disconnect ? &unmounted : NULL);
|
|
|
if (mnt_has_parent(p)) {
|
|
|
mnt_add_count(p->mnt_parent, -1);
|
|
|
- umount_mnt(p);
|
|
|
+ if (!disconnect) {
|
|
|
+ /* Don't forget about p */
|
|
|
+ list_add_tail(&p->mnt_child, &p->mnt_parent->mnt_mounts);
|
|
|
+ } else {
|
|
|
+ umount_mnt(p);
|
|
|
+ }
|
|
|
}
|
|
|
change_mnt_propagation(p, MS_PRIVATE);
|
|
|
}
|
|
@@ -1506,7 +1522,14 @@ void __detach_mounts(struct dentry *dentry)
|
|
|
lock_mount_hash();
|
|
|
while (!hlist_empty(&mp->m_list)) {
|
|
|
mnt = hlist_entry(mp->m_list.first, struct mount, mnt_mp_list);
|
|
|
- umount_tree(mnt, 0);
|
|
|
+ if (mnt->mnt.mnt_flags & MNT_UMOUNT) {
|
|
|
+ struct mount *p, *tmp;
|
|
|
+ list_for_each_entry_safe(p, tmp, &mnt->mnt_mounts, mnt_child) {
|
|
|
+ hlist_add_head(&p->mnt_umount.s_list, &unmounted);
|
|
|
+ umount_mnt(p);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else umount_tree(mnt, 0);
|
|
|
}
|
|
|
unlock_mount_hash();
|
|
|
put_mountpoint(mp);
|