diff options
| -rw-r--r-- | fs/namespace.c | 29 | ||||
| -rw-r--r-- | fs/pnode.h | 2 |
2 files changed, 28 insertions, 3 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 010d5bebcb7e..1894d1878dbc 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -1099,6 +1099,13 @@ static void mntput_no_expire(struct mount *mnt) | |||
| 1099 | rcu_read_unlock(); | 1099 | rcu_read_unlock(); |
| 1100 | 1100 | ||
| 1101 | list_del(&mnt->mnt_instance); | 1101 | list_del(&mnt->mnt_instance); |
| 1102 | |||
| 1103 | if (unlikely(!list_empty(&mnt->mnt_mounts))) { | ||
| 1104 | struct mount *p, *tmp; | ||
| 1105 | list_for_each_entry_safe(p, tmp, &mnt->mnt_mounts, mnt_child) { | ||
| 1106 | umount_mnt(p); | ||
| 1107 | } | ||
| 1108 | } | ||
| 1102 | unlock_mount_hash(); | 1109 | unlock_mount_hash(); |
| 1103 | 1110 | ||
| 1104 | if (likely(!(mnt->mnt.mnt_flags & MNT_INTERNAL))) { | 1111 | if (likely(!(mnt->mnt.mnt_flags & MNT_INTERNAL))) { |
| @@ -1370,6 +1377,7 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how) | |||
| 1370 | propagate_umount(&tmp_list); | 1377 | propagate_umount(&tmp_list); |
| 1371 | 1378 | ||
| 1372 | while (!list_empty(&tmp_list)) { | 1379 | while (!list_empty(&tmp_list)) { |
| 1380 | bool disconnect; | ||
| 1373 | p = list_first_entry(&tmp_list, struct mount, mnt_list); | 1381 | p = list_first_entry(&tmp_list, struct mount, mnt_list); |
| 1374 | list_del_init(&p->mnt_expire); | 1382 | list_del_init(&p->mnt_expire); |
| 1375 | list_del_init(&p->mnt_list); | 1383 | list_del_init(&p->mnt_list); |
| @@ -1378,10 +1386,18 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how) | |||
| 1378 | if (how & UMOUNT_SYNC) | 1386 | if (how & UMOUNT_SYNC) |
| 1379 | p->mnt.mnt_flags |= MNT_SYNC_UMOUNT; | 1387 | p->mnt.mnt_flags |= MNT_SYNC_UMOUNT; |
| 1380 | 1388 | ||
| 1381 | pin_insert_group(&p->mnt_umount, &p->mnt_parent->mnt, &unmounted); | 1389 | disconnect = !IS_MNT_LOCKED_AND_LAZY(p); |
| 1390 | |||
| 1391 | pin_insert_group(&p->mnt_umount, &p->mnt_parent->mnt, | ||
| 1392 | disconnect ? &unmounted : NULL); | ||
| 1382 | if (mnt_has_parent(p)) { | 1393 | if (mnt_has_parent(p)) { |
| 1383 | mnt_add_count(p->mnt_parent, -1); | 1394 | mnt_add_count(p->mnt_parent, -1); |
| 1384 | umount_mnt(p); | 1395 | if (!disconnect) { |
| 1396 | /* Don't forget about p */ | ||
| 1397 | list_add_tail(&p->mnt_child, &p->mnt_parent->mnt_mounts); | ||
| 1398 | } else { | ||
| 1399 | umount_mnt(p); | ||
| 1400 | } | ||
| 1385 | } | 1401 | } |
| 1386 | change_mnt_propagation(p, MS_PRIVATE); | 1402 | change_mnt_propagation(p, MS_PRIVATE); |
| 1387 | } | 1403 | } |
| @@ -1506,7 +1522,14 @@ void __detach_mounts(struct dentry *dentry) | |||
| 1506 | lock_mount_hash(); | 1522 | lock_mount_hash(); |
| 1507 | while (!hlist_empty(&mp->m_list)) { | 1523 | while (!hlist_empty(&mp->m_list)) { |
| 1508 | mnt = hlist_entry(mp->m_list.first, struct mount, mnt_mp_list); | 1524 | mnt = hlist_entry(mp->m_list.first, struct mount, mnt_mp_list); |
| 1509 | umount_tree(mnt, 0); | 1525 | if (mnt->mnt.mnt_flags & MNT_UMOUNT) { |
| 1526 | struct mount *p, *tmp; | ||
| 1527 | list_for_each_entry_safe(p, tmp, &mnt->mnt_mounts, mnt_child) { | ||
| 1528 | hlist_add_head(&p->mnt_umount.s_list, &unmounted); | ||
| 1529 | umount_mnt(p); | ||
| 1530 | } | ||
| 1531 | } | ||
| 1532 | else umount_tree(mnt, 0); | ||
| 1510 | } | 1533 | } |
| 1511 | unlock_mount_hash(); | 1534 | unlock_mount_hash(); |
| 1512 | put_mountpoint(mp); | 1535 | put_mountpoint(mp); |
diff --git a/fs/pnode.h b/fs/pnode.h index 0fcdbe7ca648..7114ce6e6b9e 100644 --- a/fs/pnode.h +++ b/fs/pnode.h | |||
| @@ -20,6 +20,8 @@ | |||
| 20 | #define SET_MNT_MARK(m) ((m)->mnt.mnt_flags |= MNT_MARKED) | 20 | #define SET_MNT_MARK(m) ((m)->mnt.mnt_flags |= MNT_MARKED) |
| 21 | #define CLEAR_MNT_MARK(m) ((m)->mnt.mnt_flags &= ~MNT_MARKED) | 21 | #define CLEAR_MNT_MARK(m) ((m)->mnt.mnt_flags &= ~MNT_MARKED) |
| 22 | #define IS_MNT_LOCKED(m) ((m)->mnt.mnt_flags & MNT_LOCKED) | 22 | #define IS_MNT_LOCKED(m) ((m)->mnt.mnt_flags & MNT_LOCKED) |
| 23 | #define IS_MNT_LOCKED_AND_LAZY(m) \ | ||
| 24 | (((m)->mnt.mnt_flags & (MNT_LOCKED|MNT_SYNC_UMOUNT)) == MNT_LOCKED) | ||
| 23 | 25 | ||
| 24 | #define CL_EXPIRE 0x01 | 26 | #define CL_EXPIRE 0x01 |
| 25 | #define CL_SLAVE 0x02 | 27 | #define CL_SLAVE 0x02 |
