diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2014-12-22 20:12:07 -0500 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2015-04-02 21:34:19 -0400 |
commit | 411a938b5abc9cb126c41cccf5975ae464fe0f3e (patch) | |
tree | 730e8410fbeb2ec8190b9b2352abf80ffd56f0ce /fs | |
parent | 590ce4bcbfb4e0462a720a4ad901e84416080bba (diff) |
mnt: Delay removal from the mount hash.
- Modify __lookup_mnt_hash_last to ignore mounts that have MNT_UMOUNTED set.
- Don't remove mounts from the mount hash table in propogate_umount
- Don't remove mounts from the mount hash table in umount_tree before
the entire list of mounts to be umounted is selected.
- Remove mounts from the mount hash table as the last thing that
happens in the case where a mount has a parent in umount_tree.
Mounts without parents are not hashed (by definition).
This paves the way for delaying removal from the mount hash table even
farther and fixing the MNT_LOCKED vs MNT_DETACH issue.
Cc: stable@vger.kernel.org
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/namespace.c | 13 | ||||
-rw-r--r-- | fs/pnode.c | 1 |
2 files changed, 8 insertions, 6 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index d1708147eb45..083e3401a808 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 | */ |
633 | struct mount *__lookup_mnt_last(struct vfsmount *mnt, struct dentry *dentry) | 633 | struct 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 | } |
644 | out: | 647 | out: |
645 | return res; | 648 | return res; |
@@ -1336,9 +1339,8 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how) | |||
1336 | list_move(&p->mnt_list, &tmp_list); | 1339 | list_move(&p->mnt_list, &tmp_list); |
1337 | } | 1340 | } |
1338 | 1341 | ||
1339 | /* Hide the mounts from lookup_mnt and mnt_mounts */ | 1342 | /* Hide the mounts from mnt_mounts */ |
1340 | list_for_each_entry(p, &tmp_list, mnt_list) { | 1343 | list_for_each_entry(p, &tmp_list, mnt_list) { |
1341 | hlist_del_init_rcu(&p->mnt_hash); | ||
1342 | list_del_init(&p->mnt_child); | 1344 | list_del_init(&p->mnt_child); |
1343 | } | 1345 | } |
1344 | 1346 | ||
@@ -1365,6 +1367,7 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how) | |||
1365 | p->mnt_mountpoint = p->mnt.mnt_root; | 1367 | p->mnt_mountpoint = p->mnt.mnt_root; |
1366 | p->mnt_parent = p; | 1368 | p->mnt_parent = p; |
1367 | p->mnt_mp = NULL; | 1369 | p->mnt_mp = NULL; |
1370 | hlist_del_init_rcu(&p->mnt_hash); | ||
1368 | } | 1371 | } |
1369 | change_mnt_propagation(p, MS_PRIVATE); | 1372 | change_mnt_propagation(p, MS_PRIVATE); |
1370 | } | 1373 | } |
diff --git a/fs/pnode.c b/fs/pnode.c index ac3aa0d43b90..c27ae38ee250 100644 --- a/fs/pnode.c +++ b/fs/pnode.c | |||
@@ -383,7 +383,6 @@ static void __propagate_umount(struct mount *mnt) | |||
383 | */ | 383 | */ |
384 | if (child && list_empty(&child->mnt_mounts)) { | 384 | if (child && list_empty(&child->mnt_mounts)) { |
385 | list_del_init(&child->mnt_child); | 385 | list_del_init(&child->mnt_child); |
386 | hlist_del_init_rcu(&child->mnt_hash); | ||
387 | child->mnt.mnt_flags |= MNT_UMOUNT; | 386 | child->mnt.mnt_flags |= MNT_UMOUNT; |
388 | list_move_tail(&child->mnt_list, &mnt->mnt_list); | 387 | list_move_tail(&child->mnt_list, &mnt->mnt_list); |
389 | } | 388 | } |