diff options
| -rw-r--r-- | fs/namespace.c | 32 |
1 files changed, 23 insertions, 9 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 3b648da55d87..9db3ce397a83 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -621,12 +621,20 @@ struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry) | |||
| 621 | struct mount *__lookup_mnt_last(struct vfsmount *mnt, struct dentry *dentry) | 621 | struct mount *__lookup_mnt_last(struct vfsmount *mnt, struct dentry *dentry) |
| 622 | { | 622 | { |
| 623 | struct list_head *head = m_hash(mnt, dentry); | 623 | struct list_head *head = m_hash(mnt, dentry); |
| 624 | struct mount *p; | 624 | struct mount *p, *res = NULL; |
| 625 | 625 | ||
| 626 | list_for_each_entry_reverse(p, head, mnt_hash) | 626 | list_for_each_entry(p, head, mnt_hash) |
| 627 | if (&p->mnt_parent->mnt == mnt && p->mnt_mountpoint == dentry) | 627 | if (&p->mnt_parent->mnt == mnt && p->mnt_mountpoint == dentry) |
| 628 | return p; | 628 | goto found; |
| 629 | return NULL; | 629 | return res; |
| 630 | found: | ||
| 631 | res = p; | ||
| 632 | list_for_each_entry_continue(p, head, mnt_hash) { | ||
| 633 | if (&p->mnt_parent->mnt != mnt || p->mnt_mountpoint != dentry) | ||
| 634 | break; | ||
| 635 | res = p; | ||
| 636 | } | ||
| 637 | return res; | ||
| 630 | } | 638 | } |
| 631 | 639 | ||
| 632 | /* | 640 | /* |
| @@ -769,14 +777,14 @@ static void attach_mnt(struct mount *mnt, | |||
| 769 | struct mountpoint *mp) | 777 | struct mountpoint *mp) |
| 770 | { | 778 | { |
| 771 | mnt_set_mountpoint(parent, mp, mnt); | 779 | mnt_set_mountpoint(parent, mp, mnt); |
| 772 | list_add_tail(&mnt->mnt_hash, m_hash(&parent->mnt, mp->m_dentry)); | 780 | list_add(&mnt->mnt_hash, m_hash(&parent->mnt, mp->m_dentry)); |
| 773 | list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); | 781 | list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); |
| 774 | } | 782 | } |
| 775 | 783 | ||
| 776 | /* | 784 | /* |
| 777 | * vfsmount lock must be held for write | 785 | * vfsmount lock must be held for write |
| 778 | */ | 786 | */ |
| 779 | static void commit_tree(struct mount *mnt) | 787 | static void commit_tree(struct mount *mnt, struct mount *shadows) |
| 780 | { | 788 | { |
| 781 | struct mount *parent = mnt->mnt_parent; | 789 | struct mount *parent = mnt->mnt_parent; |
| 782 | struct mount *m; | 790 | struct mount *m; |
| @@ -791,7 +799,10 @@ static void commit_tree(struct mount *mnt) | |||
| 791 | 799 | ||
| 792 | list_splice(&head, n->list.prev); | 800 | list_splice(&head, n->list.prev); |
| 793 | 801 | ||
| 794 | list_add_tail(&mnt->mnt_hash, | 802 | if (shadows) |
| 803 | list_add(&mnt->mnt_hash, &shadows->mnt_hash); | ||
| 804 | else | ||
| 805 | list_add(&mnt->mnt_hash, | ||
| 795 | m_hash(&parent->mnt, mnt->mnt_mountpoint)); | 806 | m_hash(&parent->mnt, mnt->mnt_mountpoint)); |
| 796 | list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); | 807 | list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); |
| 797 | touch_mnt_namespace(n); | 808 | touch_mnt_namespace(n); |
| @@ -1659,12 +1670,15 @@ static int attach_recursive_mnt(struct mount *source_mnt, | |||
| 1659 | touch_mnt_namespace(source_mnt->mnt_ns); | 1670 | touch_mnt_namespace(source_mnt->mnt_ns); |
| 1660 | } else { | 1671 | } else { |
| 1661 | mnt_set_mountpoint(dest_mnt, dest_mp, source_mnt); | 1672 | mnt_set_mountpoint(dest_mnt, dest_mp, source_mnt); |
| 1662 | commit_tree(source_mnt); | 1673 | commit_tree(source_mnt, NULL); |
| 1663 | } | 1674 | } |
| 1664 | 1675 | ||
| 1665 | list_for_each_entry_safe(child, p, &tree_list, mnt_hash) { | 1676 | list_for_each_entry_safe(child, p, &tree_list, mnt_hash) { |
| 1677 | struct mount *q; | ||
| 1666 | list_del_init(&child->mnt_hash); | 1678 | list_del_init(&child->mnt_hash); |
| 1667 | commit_tree(child); | 1679 | q = __lookup_mnt_last(&child->mnt_parent->mnt, |
| 1680 | child->mnt_mountpoint); | ||
| 1681 | commit_tree(child, q); | ||
| 1668 | } | 1682 | } |
| 1669 | unlock_mount_hash(); | 1683 | unlock_mount_hash(); |
| 1670 | 1684 | ||
