@@ -650,13 +650,11 @@ struct mount *__lookup_mnt_last(struct vfsmount *mnt, struct dentry *dentry)
p = __lookup_mnt(mnt, dentry);
if (!p)
goto out;
- if (!(p->mnt.mnt_flags & MNT_UMOUNT))
- res = p;
+ res = p;
hlist_for_each_entry_continue(p, mnt_hash) {
if (&p->mnt_parent->mnt != mnt || p->mnt_mountpoint != dentry)
break;
- if (!(p->mnt.mnt_flags & MNT_UMOUNT))
- res = p;
+ res = p;
}
out:
return res;
@@ -399,11 +399,18 @@ static void mark_umount_candidates(struct mount *mnt)
BUG_ON(parent == mnt);
+ if (IS_MNT_MARKED(mnt))
+ return;
+
+ SET_MNT_MARK(mnt);
+
for (m = propagation_next(parent, parent); m;
m = propagation_next(m, parent)) {
struct mount *child = __lookup_mnt_last(&m->mnt,
mnt->mnt_mountpoint);
- if (child && (!IS_MNT_LOCKED(child) || IS_MNT_MARKED(m))) {
+ if (child && ((child->mnt.mnt_flags & MNT_UMOUNT) ||
+ !IS_MNT_LOCKED(child) ||
+ IS_MNT_MARKED(m))) {
SET_MNT_MARK(child);
}
}
@@ -420,6 +427,11 @@ static void __propagate_umount(struct mount *mnt)
BUG_ON(parent == mnt);
+ if (!IS_MNT_MARKED(mnt))
+ return;
+
+ CLEAR_MNT_MARK(mnt);
+
for (m = propagation_next(parent, parent); m;
m = propagation_next(m, parent)) {
@@ -432,7 +444,8 @@ static void __propagate_umount(struct mount *mnt)
if (!child || !IS_MNT_MARKED(child))
continue;
CLEAR_MNT_MARK(child);
- if (list_empty(&child->mnt_mounts)) {
+ if (!(child->mnt.mnt_flags & MNT_UMOUNT) &&
+ list_empty(&child->mnt_mounts)) {
list_del_init(&child->mnt_child);
child->mnt.mnt_flags |= MNT_UMOUNT;
list_move_tail(&child->mnt_list, &mnt->mnt_list);