aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namespace.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c42
1 files changed, 33 insertions, 9 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index c7cb8a526c05..2b8aa15fd6df 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1361,6 +1361,36 @@ enum umount_tree_flags {
1361 UMOUNT_PROPAGATE = 2, 1361 UMOUNT_PROPAGATE = 2,
1362 UMOUNT_CONNECTED = 4, 1362 UMOUNT_CONNECTED = 4,
1363}; 1363};
1364
1365static bool disconnect_mount(struct mount *mnt, enum umount_tree_flags how)
1366{
1367 /* Leaving mounts connected is only valid for lazy umounts */
1368 if (how & UMOUNT_SYNC)
1369 return true;
1370
1371 /* A mount without a parent has nothing to be connected to */
1372 if (!mnt_has_parent(mnt))
1373 return true;
1374
1375 /* Because the reference counting rules change when mounts are
1376 * unmounted and connected, umounted mounts may not be
1377 * connected to mounted mounts.
1378 */
1379 if (!(mnt->mnt_parent->mnt.mnt_flags & MNT_UMOUNT))
1380 return true;
1381
1382 /* Has it been requested that the mount remain connected? */
1383 if (how & UMOUNT_CONNECTED)
1384 return false;
1385
1386 /* Is the mount locked such that it needs to remain connected? */
1387 if (IS_MNT_LOCKED(mnt))
1388 return false;
1389
1390 /* By default disconnect the mount */
1391 return true;
1392}
1393
1364/* 1394/*
1365 * mount_lock must be held 1395 * mount_lock must be held
1366 * namespace_sem must be held for write 1396 * namespace_sem must be held for write
@@ -1398,10 +1428,7 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how)
1398 if (how & UMOUNT_SYNC) 1428 if (how & UMOUNT_SYNC)
1399 p->mnt.mnt_flags |= MNT_SYNC_UMOUNT; 1429 p->mnt.mnt_flags |= MNT_SYNC_UMOUNT;
1400 1430
1401 disconnect = !(((how & UMOUNT_CONNECTED) && 1431 disconnect = disconnect_mount(p, how);
1402 mnt_has_parent(p) &&
1403 (p->mnt_parent->mnt.mnt_flags & MNT_UMOUNT)) ||
1404 IS_MNT_LOCKED_AND_LAZY(p));
1405 1432
1406 pin_insert_group(&p->mnt_umount, &p->mnt_parent->mnt, 1433 pin_insert_group(&p->mnt_umount, &p->mnt_parent->mnt,
1407 disconnect ? &unmounted : NULL); 1434 disconnect ? &unmounted : NULL);
@@ -1538,11 +1565,8 @@ void __detach_mounts(struct dentry *dentry)
1538 while (!hlist_empty(&mp->m_list)) { 1565 while (!hlist_empty(&mp->m_list)) {
1539 mnt = hlist_entry(mp->m_list.first, struct mount, mnt_mp_list); 1566 mnt = hlist_entry(mp->m_list.first, struct mount, mnt_mp_list);
1540 if (mnt->mnt.mnt_flags & MNT_UMOUNT) { 1567 if (mnt->mnt.mnt_flags & MNT_UMOUNT) {
1541 struct mount *p, *tmp; 1568 hlist_add_head(&mnt->mnt_umount.s_list, &unmounted);
1542 list_for_each_entry_safe(p, tmp, &mnt->mnt_mounts, mnt_child) { 1569 umount_mnt(mnt);
1543 hlist_add_head(&p->mnt_umount.s_list, &unmounted);
1544 umount_mnt(p);
1545 }
1546 } 1570 }
1547 else umount_tree(mnt, UMOUNT_CONNECTED); 1571 else umount_tree(mnt, UMOUNT_CONNECTED);
1548 } 1572 }