aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-04-18 11:20:31 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-18 11:20:31 -0400
commit8f502d5b9e3362971f58dad5d468f070340336e1 (patch)
treefa819b5acdfc43c01e3696991ffe90836f265a34 /fs
parent06a60deca87dba8e2c186ea7f12ea87d6785188e (diff)
parente0c9c0afd2fc958ffa34b697972721d81df8a56f (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace
Pull usernamespace mount fixes from Eric Biederman: "Way back in October Andrey Vagin reported that umount(MNT_DETACH) could be used to defeat MNT_LOCKED. As I worked to fix this I discovered that combined with mount propagation and an appropriate selection of shared subtrees a reference to a directory on an unmounted filesystem is not necessary. That MNT_DETACH is allowed in user namespace in a form that can break MNT_LOCKED comes from my early misunderstanding what MNT_DETACH does. To avoid breaking existing userspace the conflict between MNT_DETACH and MNT_LOCKED is fixed by leaving mounts that are locked to their parents in the mount hash table until the last reference goes away. While investigating this issue I also found an issue with __detach_mounts. The code was unnecessarily and incorrectly triggering mount propagation. Resulting in too many mounts going away when a directory is deleted, and too many cpu cycles are burned while doing that. Looking some more I realized that __detach_mounts by only keeping mounts connected that were MNT_LOCKED it had the potential to still leak information so I tweaked the code to keep everything locked together that possibly could be. This code was almost ready last cycle but Al invented fs_pin which slightly simplifies this code but required rewrites and retesting, and I have not been in top form for a while so it took me a while to get all of that done. Similiarly this pull request is late because I have been feeling absolutely miserable all week. The issue of being able to escape a bind mount has not yet been addressed, as the fixes are not yet mature" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: mnt: Update detach_mounts to leave mounts connected mnt: Fix the error check in __detach_mounts mnt: Honor MNT_LOCKED when detaching mounts fs_pin: Allow for the possibility that m_list or s_list go unused. mnt: Factor umount_mnt from umount_tree mnt: Factor out unhash_mnt from detach_mnt and umount_tree mnt: Fail collect_mounts when applied to unmounted mounts mnt: Don't propagate unmounts to locked mounts mnt: On an unmount propagate clearing of MNT_LOCKED mnt: Delay removal from the mount hash. mnt: Add MNT_UMOUNT flag mnt: In umount_tree reuse mnt_list instead of mnt_hash mnt: Don't propagate umounts in __detach_mounts mnt: Improve the umount_tree flags mnt: Use hlist_move_list in namespace_unlock
Diffstat (limited to 'fs')
-rw-r--r--fs/fs_pin.c4
-rw-r--r--fs/namespace.c142
-rw-r--r--fs/pnode.c60
-rw-r--r--fs/pnode.h7
4 files changed, 156 insertions, 57 deletions
diff --git a/fs/fs_pin.c b/fs/fs_pin.c
index b06c98796afb..611b5408f6ec 100644
--- a/fs/fs_pin.c
+++ b/fs/fs_pin.c
@@ -9,8 +9,8 @@ static DEFINE_SPINLOCK(pin_lock);
9void pin_remove(struct fs_pin *pin) 9void pin_remove(struct fs_pin *pin)
10{ 10{
11 spin_lock(&pin_lock); 11 spin_lock(&pin_lock);
12 hlist_del(&pin->m_list); 12 hlist_del_init(&pin->m_list);
13 hlist_del(&pin->s_list); 13 hlist_del_init(&pin->s_list);
14 spin_unlock(&pin_lock); 14 spin_unlock(&pin_lock);
15 spin_lock_irq(&pin->wait.lock); 15 spin_lock_irq(&pin->wait.lock);
16 pin->done = 1; 16 pin->done = 1;
diff --git a/fs/namespace.c b/fs/namespace.c
index 82ef1405260e..1f4f9dac6e5a 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -632,14 +632,17 @@ struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry)
632 */ 632 */
633struct mount *__lookup_mnt_last(struct vfsmount *mnt, struct dentry *dentry) 633struct mount *__lookup_mnt_last(struct vfsmount *mnt, struct dentry *dentry)
634{ 634{
635 struct mount *p, *res; 635 struct mount *p, *res = NULL;
636 res = p = __lookup_mnt(mnt, dentry); 636 p = __lookup_mnt(mnt, dentry);
637 if (!p) 637 if (!p)
638 goto out; 638 goto out;
639 if (!(p->mnt.mnt_flags & MNT_UMOUNT))
640 res = p;
639 hlist_for_each_entry_continue(p, mnt_hash) { 641 hlist_for_each_entry_continue(p, mnt_hash) {
640 if (&p->mnt_parent->mnt != mnt || p->mnt_mountpoint != dentry) 642 if (&p->mnt_parent->mnt != mnt || p->mnt_mountpoint != dentry)
641 break; 643 break;
642 res = p; 644 if (!(p->mnt.mnt_flags & MNT_UMOUNT))
645 res = p;
643 } 646 }
644out: 647out:
645 return res; 648 return res;
@@ -795,10 +798,8 @@ static void __touch_mnt_namespace(struct mnt_namespace *ns)
795/* 798/*
796 * vfsmount lock must be held for write 799 * vfsmount lock must be held for write
797 */ 800 */
798static void detach_mnt(struct mount *mnt, struct path *old_path) 801static void unhash_mnt(struct mount *mnt)
799{ 802{
800 old_path->dentry = mnt->mnt_mountpoint;
801 old_path->mnt = &mnt->mnt_parent->mnt;
802 mnt->mnt_parent = mnt; 803 mnt->mnt_parent = mnt;
803 mnt->mnt_mountpoint = mnt->mnt.mnt_root; 804 mnt->mnt_mountpoint = mnt->mnt.mnt_root;
804 list_del_init(&mnt->mnt_child); 805 list_del_init(&mnt->mnt_child);
@@ -811,6 +812,26 @@ static void detach_mnt(struct mount *mnt, struct path *old_path)
811/* 812/*
812 * vfsmount lock must be held for write 813 * vfsmount lock must be held for write
813 */ 814 */
815static void detach_mnt(struct mount *mnt, struct path *old_path)
816{
817 old_path->dentry = mnt->mnt_mountpoint;
818 old_path->mnt = &mnt->mnt_parent->mnt;
819 unhash_mnt(mnt);
820}
821
822/*
823 * vfsmount lock must be held for write
824 */
825static void umount_mnt(struct mount *mnt)
826{
827 /* old mountpoint will be dropped when we can do that */
828 mnt->mnt_ex_mountpoint = mnt->mnt_mountpoint;
829 unhash_mnt(mnt);
830}
831
832/*
833 * vfsmount lock must be held for write
834 */
814void mnt_set_mountpoint(struct mount *mnt, 835void mnt_set_mountpoint(struct mount *mnt,
815 struct mountpoint *mp, 836 struct mountpoint *mp,
816 struct mount *child_mnt) 837 struct mount *child_mnt)
@@ -1078,6 +1099,13 @@ static void mntput_no_expire(struct mount *mnt)
1078 rcu_read_unlock(); 1099 rcu_read_unlock();
1079 1100
1080 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 }
1081 unlock_mount_hash(); 1109 unlock_mount_hash();
1082 1110
1083 if (likely(!(mnt->mnt.mnt_flags & MNT_INTERNAL))) { 1111 if (likely(!(mnt->mnt.mnt_flags & MNT_INTERNAL))) {
@@ -1298,17 +1326,15 @@ static HLIST_HEAD(unmounted); /* protected by namespace_sem */
1298 1326
1299static void namespace_unlock(void) 1327static void namespace_unlock(void)
1300{ 1328{
1301 struct hlist_head head = unmounted; 1329 struct hlist_head head;
1302 1330
1303 if (likely(hlist_empty(&head))) { 1331 hlist_move_list(&unmounted, &head);
1304 up_write(&namespace_sem);
1305 return;
1306 }
1307 1332
1308 head.first->pprev = &head.first;
1309 INIT_HLIST_HEAD(&unmounted);
1310 up_write(&namespace_sem); 1333 up_write(&namespace_sem);
1311 1334
1335 if (likely(hlist_empty(&head)))
1336 return;
1337
1312 synchronize_rcu(); 1338 synchronize_rcu();
1313 1339
1314 group_pin_kill(&head); 1340 group_pin_kill(&head);
@@ -1319,49 +1345,63 @@ static inline void namespace_lock(void)
1319 down_write(&namespace_sem); 1345 down_write(&namespace_sem);
1320} 1346}
1321 1347
1348enum umount_tree_flags {
1349 UMOUNT_SYNC = 1,
1350 UMOUNT_PROPAGATE = 2,
1351 UMOUNT_CONNECTED = 4,
1352};
1322/* 1353/*
1323 * mount_lock must be held 1354 * mount_lock must be held
1324 * namespace_sem must be held for write 1355 * namespace_sem must be held for write
1325 * how = 0 => just this tree, don't propagate
1326 * how = 1 => propagate; we know that nobody else has reference to any victims
1327 * how = 2 => lazy umount
1328 */ 1356 */
1329void umount_tree(struct mount *mnt, int how) 1357static void umount_tree(struct mount *mnt, enum umount_tree_flags how)
1330{ 1358{
1331 HLIST_HEAD(tmp_list); 1359 LIST_HEAD(tmp_list);
1332 struct mount *p; 1360 struct mount *p;
1333 1361
1362 if (how & UMOUNT_PROPAGATE)
1363 propagate_mount_unlock(mnt);
1364
1365 /* Gather the mounts to umount */
1334 for (p = mnt; p; p = next_mnt(p, mnt)) { 1366 for (p = mnt; p; p = next_mnt(p, mnt)) {
1335 hlist_del_init_rcu(&p->mnt_hash); 1367 p->mnt.mnt_flags |= MNT_UMOUNT;
1336 hlist_add_head(&p->mnt_hash, &tmp_list); 1368 list_move(&p->mnt_list, &tmp_list);
1337 } 1369 }
1338 1370
1339 hlist_for_each_entry(p, &tmp_list, mnt_hash) 1371 /* Hide the mounts from mnt_mounts */
1372 list_for_each_entry(p, &tmp_list, mnt_list) {
1340 list_del_init(&p->mnt_child); 1373 list_del_init(&p->mnt_child);
1374 }
1341 1375
1342 if (how) 1376 /* Add propogated mounts to the tmp_list */
1377 if (how & UMOUNT_PROPAGATE)
1343 propagate_umount(&tmp_list); 1378 propagate_umount(&tmp_list);
1344 1379
1345 while (!hlist_empty(&tmp_list)) { 1380 while (!list_empty(&tmp_list)) {
1346 p = hlist_entry(tmp_list.first, struct mount, mnt_hash); 1381 bool disconnect;
1347 hlist_del_init_rcu(&p->mnt_hash); 1382 p = list_first_entry(&tmp_list, struct mount, mnt_list);
1348 list_del_init(&p->mnt_expire); 1383 list_del_init(&p->mnt_expire);
1349 list_del_init(&p->mnt_list); 1384 list_del_init(&p->mnt_list);
1350 __touch_mnt_namespace(p->mnt_ns); 1385 __touch_mnt_namespace(p->mnt_ns);
1351 p->mnt_ns = NULL; 1386 p->mnt_ns = NULL;
1352 if (how < 2) 1387 if (how & UMOUNT_SYNC)
1353 p->mnt.mnt_flags |= MNT_SYNC_UMOUNT; 1388 p->mnt.mnt_flags |= MNT_SYNC_UMOUNT;
1354 1389
1355 pin_insert_group(&p->mnt_umount, &p->mnt_parent->mnt, &unmounted); 1390 disconnect = !(((how & UMOUNT_CONNECTED) &&
1391 mnt_has_parent(p) &&
1392 (p->mnt_parent->mnt.mnt_flags & MNT_UMOUNT)) ||
1393 IS_MNT_LOCKED_AND_LAZY(p));
1394
1395 pin_insert_group(&p->mnt_umount, &p->mnt_parent->mnt,
1396 disconnect ? &unmounted : NULL);
1356 if (mnt_has_parent(p)) { 1397 if (mnt_has_parent(p)) {
1357 hlist_del_init(&p->mnt_mp_list);
1358 put_mountpoint(p->mnt_mp);
1359 mnt_add_count(p->mnt_parent, -1); 1398 mnt_add_count(p->mnt_parent, -1);
1360 /* old mountpoint will be dropped when we can do that */ 1399 if (!disconnect) {
1361 p->mnt_ex_mountpoint = p->mnt_mountpoint; 1400 /* Don't forget about p */
1362 p->mnt_mountpoint = p->mnt.mnt_root; 1401 list_add_tail(&p->mnt_child, &p->mnt_parent->mnt_mounts);
1363 p->mnt_parent = p; 1402 } else {
1364 p->mnt_mp = NULL; 1403 umount_mnt(p);
1404 }
1365 } 1405 }
1366 change_mnt_propagation(p, MS_PRIVATE); 1406 change_mnt_propagation(p, MS_PRIVATE);
1367 } 1407 }
@@ -1447,14 +1487,14 @@ static int do_umount(struct mount *mnt, int flags)
1447 1487
1448 if (flags & MNT_DETACH) { 1488 if (flags & MNT_DETACH) {
1449 if (!list_empty(&mnt->mnt_list)) 1489 if (!list_empty(&mnt->mnt_list))
1450 umount_tree(mnt, 2); 1490 umount_tree(mnt, UMOUNT_PROPAGATE);
1451 retval = 0; 1491 retval = 0;
1452 } else { 1492 } else {
1453 shrink_submounts(mnt); 1493 shrink_submounts(mnt);
1454 retval = -EBUSY; 1494 retval = -EBUSY;
1455 if (!propagate_mount_busy(mnt, 2)) { 1495 if (!propagate_mount_busy(mnt, 2)) {
1456 if (!list_empty(&mnt->mnt_list)) 1496 if (!list_empty(&mnt->mnt_list))
1457 umount_tree(mnt, 1); 1497 umount_tree(mnt, UMOUNT_PROPAGATE|UMOUNT_SYNC);
1458 retval = 0; 1498 retval = 0;
1459 } 1499 }
1460 } 1500 }
@@ -1480,13 +1520,20 @@ void __detach_mounts(struct dentry *dentry)
1480 1520
1481 namespace_lock(); 1521 namespace_lock();
1482 mp = lookup_mountpoint(dentry); 1522 mp = lookup_mountpoint(dentry);
1483 if (!mp) 1523 if (IS_ERR_OR_NULL(mp))
1484 goto out_unlock; 1524 goto out_unlock;
1485 1525
1486 lock_mount_hash(); 1526 lock_mount_hash();
1487 while (!hlist_empty(&mp->m_list)) { 1527 while (!hlist_empty(&mp->m_list)) {
1488 mnt = hlist_entry(mp->m_list.first, struct mount, mnt_mp_list); 1528 mnt = hlist_entry(mp->m_list.first, struct mount, mnt_mp_list);
1489 umount_tree(mnt, 2); 1529 if (mnt->mnt.mnt_flags & MNT_UMOUNT) {
1530 struct mount *p, *tmp;
1531 list_for_each_entry_safe(p, tmp, &mnt->mnt_mounts, mnt_child) {
1532 hlist_add_head(&p->mnt_umount.s_list, &unmounted);
1533 umount_mnt(p);
1534 }
1535 }
1536 else umount_tree(mnt, UMOUNT_CONNECTED);
1490 } 1537 }
1491 unlock_mount_hash(); 1538 unlock_mount_hash();
1492 put_mountpoint(mp); 1539 put_mountpoint(mp);
@@ -1648,7 +1695,7 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
1648out: 1695out:
1649 if (res) { 1696 if (res) {
1650 lock_mount_hash(); 1697 lock_mount_hash();
1651 umount_tree(res, 0); 1698 umount_tree(res, UMOUNT_SYNC);
1652 unlock_mount_hash(); 1699 unlock_mount_hash();
1653 } 1700 }
1654 return q; 1701 return q;
@@ -1660,8 +1707,11 @@ struct vfsmount *collect_mounts(struct path *path)
1660{ 1707{
1661 struct mount *tree; 1708 struct mount *tree;
1662 namespace_lock(); 1709 namespace_lock();
1663 tree = copy_tree(real_mount(path->mnt), path->dentry, 1710 if (!check_mnt(real_mount(path->mnt)))
1664 CL_COPY_ALL | CL_PRIVATE); 1711 tree = ERR_PTR(-EINVAL);
1712 else
1713 tree = copy_tree(real_mount(path->mnt), path->dentry,
1714 CL_COPY_ALL | CL_PRIVATE);
1665 namespace_unlock(); 1715 namespace_unlock();
1666 if (IS_ERR(tree)) 1716 if (IS_ERR(tree))
1667 return ERR_CAST(tree); 1717 return ERR_CAST(tree);
@@ -1672,7 +1722,7 @@ void drop_collected_mounts(struct vfsmount *mnt)
1672{ 1722{
1673 namespace_lock(); 1723 namespace_lock();
1674 lock_mount_hash(); 1724 lock_mount_hash();
1675 umount_tree(real_mount(mnt), 0); 1725 umount_tree(real_mount(mnt), UMOUNT_SYNC);
1676 unlock_mount_hash(); 1726 unlock_mount_hash();
1677 namespace_unlock(); 1727 namespace_unlock();
1678} 1728}
@@ -1855,7 +1905,7 @@ static int attach_recursive_mnt(struct mount *source_mnt,
1855 out_cleanup_ids: 1905 out_cleanup_ids:
1856 while (!hlist_empty(&tree_list)) { 1906 while (!hlist_empty(&tree_list)) {
1857 child = hlist_entry(tree_list.first, struct mount, mnt_hash); 1907 child = hlist_entry(tree_list.first, struct mount, mnt_hash);
1858 umount_tree(child, 0); 1908 umount_tree(child, UMOUNT_SYNC);
1859 } 1909 }
1860 unlock_mount_hash(); 1910 unlock_mount_hash();
1861 cleanup_group_ids(source_mnt, NULL); 1911 cleanup_group_ids(source_mnt, NULL);
@@ -2035,7 +2085,7 @@ static int do_loopback(struct path *path, const char *old_name,
2035 err = graft_tree(mnt, parent, mp); 2085 err = graft_tree(mnt, parent, mp);
2036 if (err) { 2086 if (err) {
2037 lock_mount_hash(); 2087 lock_mount_hash();
2038 umount_tree(mnt, 0); 2088 umount_tree(mnt, UMOUNT_SYNC);
2039 unlock_mount_hash(); 2089 unlock_mount_hash();
2040 } 2090 }
2041out2: 2091out2:
@@ -2406,7 +2456,7 @@ void mark_mounts_for_expiry(struct list_head *mounts)
2406 while (!list_empty(&graveyard)) { 2456 while (!list_empty(&graveyard)) {
2407 mnt = list_first_entry(&graveyard, struct mount, mnt_expire); 2457 mnt = list_first_entry(&graveyard, struct mount, mnt_expire);
2408 touch_mnt_namespace(mnt->mnt_ns); 2458 touch_mnt_namespace(mnt->mnt_ns);
2409 umount_tree(mnt, 1); 2459 umount_tree(mnt, UMOUNT_PROPAGATE|UMOUNT_SYNC);
2410 } 2460 }
2411 unlock_mount_hash(); 2461 unlock_mount_hash();
2412 namespace_unlock(); 2462 namespace_unlock();
@@ -2477,7 +2527,7 @@ static void shrink_submounts(struct mount *mnt)
2477 m = list_first_entry(&graveyard, struct mount, 2527 m = list_first_entry(&graveyard, struct mount,
2478 mnt_expire); 2528 mnt_expire);
2479 touch_mnt_namespace(m->mnt_ns); 2529 touch_mnt_namespace(m->mnt_ns);
2480 umount_tree(m, 1); 2530 umount_tree(m, UMOUNT_PROPAGATE|UMOUNT_SYNC);
2481 } 2531 }
2482 } 2532 }
2483} 2533}
diff --git a/fs/pnode.c b/fs/pnode.c
index 260ac8f898a4..6367e1e435c6 100644
--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -362,6 +362,46 @@ int propagate_mount_busy(struct mount *mnt, int refcnt)
362} 362}
363 363
364/* 364/*
365 * Clear MNT_LOCKED when it can be shown to be safe.
366 *
367 * mount_lock lock must be held for write
368 */
369void propagate_mount_unlock(struct mount *mnt)
370{
371 struct mount *parent = mnt->mnt_parent;
372 struct mount *m, *child;
373
374 BUG_ON(parent == mnt);
375
376 for (m = propagation_next(parent, parent); m;
377 m = propagation_next(m, parent)) {
378 child = __lookup_mnt_last(&m->mnt, mnt->mnt_mountpoint);
379 if (child)
380 child->mnt.mnt_flags &= ~MNT_LOCKED;
381 }
382}
383
384/*
385 * Mark all mounts that the MNT_LOCKED logic will allow to be unmounted.
386 */
387static void mark_umount_candidates(struct mount *mnt)
388{
389 struct mount *parent = mnt->mnt_parent;
390 struct mount *m;
391
392 BUG_ON(parent == mnt);
393
394 for (m = propagation_next(parent, parent); m;
395 m = propagation_next(m, parent)) {
396 struct mount *child = __lookup_mnt_last(&m->mnt,
397 mnt->mnt_mountpoint);
398 if (child && (!IS_MNT_LOCKED(child) || IS_MNT_MARKED(m))) {
399 SET_MNT_MARK(child);
400 }
401 }
402}
403
404/*
365 * NOTE: unmounting 'mnt' naturally propagates to all other mounts its 405 * NOTE: unmounting 'mnt' naturally propagates to all other mounts its
366 * parent propagates to. 406 * parent propagates to.
367 */ 407 */
@@ -378,13 +418,16 @@ static void __propagate_umount(struct mount *mnt)
378 struct mount *child = __lookup_mnt_last(&m->mnt, 418 struct mount *child = __lookup_mnt_last(&m->mnt,
379 mnt->mnt_mountpoint); 419 mnt->mnt_mountpoint);
380 /* 420 /*
381 * umount the child only if the child has no 421 * umount the child only if the child has no children
382 * other children 422 * and the child is marked safe to unmount.
383 */ 423 */
384 if (child && list_empty(&child->mnt_mounts)) { 424 if (!child || !IS_MNT_MARKED(child))
425 continue;
426 CLEAR_MNT_MARK(child);
427 if (list_empty(&child->mnt_mounts)) {
385 list_del_init(&child->mnt_child); 428 list_del_init(&child->mnt_child);
386 hlist_del_init_rcu(&child->mnt_hash); 429 child->mnt.mnt_flags |= MNT_UMOUNT;
387 hlist_add_before_rcu(&child->mnt_hash, &mnt->mnt_hash); 430 list_move_tail(&child->mnt_list, &mnt->mnt_list);
388 } 431 }
389 } 432 }
390} 433}
@@ -396,11 +439,14 @@ static void __propagate_umount(struct mount *mnt)
396 * 439 *
397 * vfsmount lock must be held for write 440 * vfsmount lock must be held for write
398 */ 441 */
399int propagate_umount(struct hlist_head *list) 442int propagate_umount(struct list_head *list)
400{ 443{
401 struct mount *mnt; 444 struct mount *mnt;
402 445
403 hlist_for_each_entry(mnt, list, mnt_hash) 446 list_for_each_entry_reverse(mnt, list, mnt_list)
447 mark_umount_candidates(mnt);
448
449 list_for_each_entry(mnt, list, mnt_list)
404 __propagate_umount(mnt); 450 __propagate_umount(mnt);
405 return 0; 451 return 0;
406} 452}
diff --git a/fs/pnode.h b/fs/pnode.h
index 4a246358b031..7114ce6e6b9e 100644
--- a/fs/pnode.h
+++ b/fs/pnode.h
@@ -19,6 +19,9 @@
19#define IS_MNT_MARKED(m) ((m)->mnt.mnt_flags & MNT_MARKED) 19#define IS_MNT_MARKED(m) ((m)->mnt.mnt_flags & MNT_MARKED)
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)
23#define IS_MNT_LOCKED_AND_LAZY(m) \
24 (((m)->mnt.mnt_flags & (MNT_LOCKED|MNT_SYNC_UMOUNT)) == MNT_LOCKED)
22 25
23#define CL_EXPIRE 0x01 26#define CL_EXPIRE 0x01
24#define CL_SLAVE 0x02 27#define CL_SLAVE 0x02
@@ -40,14 +43,14 @@ static inline void set_mnt_shared(struct mount *mnt)
40void change_mnt_propagation(struct mount *, int); 43void change_mnt_propagation(struct mount *, int);
41int propagate_mnt(struct mount *, struct mountpoint *, struct mount *, 44int propagate_mnt(struct mount *, struct mountpoint *, struct mount *,
42 struct hlist_head *); 45 struct hlist_head *);
43int propagate_umount(struct hlist_head *); 46int propagate_umount(struct list_head *);
44int propagate_mount_busy(struct mount *, int); 47int propagate_mount_busy(struct mount *, int);
48void propagate_mount_unlock(struct mount *);
45void mnt_release_group_id(struct mount *); 49void mnt_release_group_id(struct mount *);
46int get_dominating_id(struct mount *mnt, const struct path *root); 50int get_dominating_id(struct mount *mnt, const struct path *root);
47unsigned int mnt_get_count(struct mount *mnt); 51unsigned int mnt_get_count(struct mount *mnt);
48void mnt_set_mountpoint(struct mount *, struct mountpoint *, 52void mnt_set_mountpoint(struct mount *, struct mountpoint *,
49 struct mount *); 53 struct mount *);
50void umount_tree(struct mount *, int);
51struct mount *copy_tree(struct mount *, struct dentry *, int); 54struct mount *copy_tree(struct mount *, struct dentry *, int);
52bool is_path_reachable(struct mount *, struct dentry *, 55bool is_path_reachable(struct mount *, struct dentry *,
53 const struct path *root); 56 const struct path *root);