18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  linux/fs/pnode.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * (C) Copyright IBM Corporation 2005.
68c2ecf20Sopenharmony_ci *	Author : Ram Pai (linuxram@us.ibm.com)
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci#include <linux/mnt_namespace.h>
98c2ecf20Sopenharmony_ci#include <linux/mount.h>
108c2ecf20Sopenharmony_ci#include <linux/fs.h>
118c2ecf20Sopenharmony_ci#include <linux/nsproxy.h>
128c2ecf20Sopenharmony_ci#include <uapi/linux/mount.h>
138c2ecf20Sopenharmony_ci#include "internal.h"
148c2ecf20Sopenharmony_ci#include "pnode.h"
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci/* return the next shared peer mount of @p */
178c2ecf20Sopenharmony_cistatic inline struct mount *next_peer(struct mount *p)
188c2ecf20Sopenharmony_ci{
198c2ecf20Sopenharmony_ci	return list_entry(p->mnt_share.next, struct mount, mnt_share);
208c2ecf20Sopenharmony_ci}
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cistatic inline struct mount *first_slave(struct mount *p)
238c2ecf20Sopenharmony_ci{
248c2ecf20Sopenharmony_ci	return list_entry(p->mnt_slave_list.next, struct mount, mnt_slave);
258c2ecf20Sopenharmony_ci}
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_cistatic inline struct mount *last_slave(struct mount *p)
288c2ecf20Sopenharmony_ci{
298c2ecf20Sopenharmony_ci	return list_entry(p->mnt_slave_list.prev, struct mount, mnt_slave);
308c2ecf20Sopenharmony_ci}
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistatic inline struct mount *next_slave(struct mount *p)
338c2ecf20Sopenharmony_ci{
348c2ecf20Sopenharmony_ci	return list_entry(p->mnt_slave.next, struct mount, mnt_slave);
358c2ecf20Sopenharmony_ci}
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_cistatic struct mount *get_peer_under_root(struct mount *mnt,
388c2ecf20Sopenharmony_ci					 struct mnt_namespace *ns,
398c2ecf20Sopenharmony_ci					 const struct path *root)
408c2ecf20Sopenharmony_ci{
418c2ecf20Sopenharmony_ci	struct mount *m = mnt;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	do {
448c2ecf20Sopenharmony_ci		/* Check the namespace first for optimization */
458c2ecf20Sopenharmony_ci		if (m->mnt_ns == ns && is_path_reachable(m, m->mnt.mnt_root, root))
468c2ecf20Sopenharmony_ci			return m;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci		m = next_peer(m);
498c2ecf20Sopenharmony_ci	} while (m != mnt);
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	return NULL;
528c2ecf20Sopenharmony_ci}
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci/*
558c2ecf20Sopenharmony_ci * Get ID of closest dominating peer group having a representative
568c2ecf20Sopenharmony_ci * under the given root.
578c2ecf20Sopenharmony_ci *
588c2ecf20Sopenharmony_ci * Caller must hold namespace_sem
598c2ecf20Sopenharmony_ci */
608c2ecf20Sopenharmony_ciint get_dominating_id(struct mount *mnt, const struct path *root)
618c2ecf20Sopenharmony_ci{
628c2ecf20Sopenharmony_ci	struct mount *m;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	for (m = mnt->mnt_master; m != NULL; m = m->mnt_master) {
658c2ecf20Sopenharmony_ci		struct mount *d = get_peer_under_root(m, mnt->mnt_ns, root);
668c2ecf20Sopenharmony_ci		if (d)
678c2ecf20Sopenharmony_ci			return d->mnt_group_id;
688c2ecf20Sopenharmony_ci	}
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	return 0;
718c2ecf20Sopenharmony_ci}
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_cistatic int do_make_slave(struct mount *mnt)
748c2ecf20Sopenharmony_ci{
758c2ecf20Sopenharmony_ci	struct mount *master, *slave_mnt;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	if (list_empty(&mnt->mnt_share)) {
788c2ecf20Sopenharmony_ci		if (IS_MNT_SHARED(mnt)) {
798c2ecf20Sopenharmony_ci			mnt_release_group_id(mnt);
808c2ecf20Sopenharmony_ci			CLEAR_MNT_SHARED(mnt);
818c2ecf20Sopenharmony_ci		}
828c2ecf20Sopenharmony_ci		master = mnt->mnt_master;
838c2ecf20Sopenharmony_ci		if (!master) {
848c2ecf20Sopenharmony_ci			struct list_head *p = &mnt->mnt_slave_list;
858c2ecf20Sopenharmony_ci			while (!list_empty(p)) {
868c2ecf20Sopenharmony_ci				slave_mnt = list_first_entry(p,
878c2ecf20Sopenharmony_ci						struct mount, mnt_slave);
888c2ecf20Sopenharmony_ci				list_del_init(&slave_mnt->mnt_slave);
898c2ecf20Sopenharmony_ci				slave_mnt->mnt_master = NULL;
908c2ecf20Sopenharmony_ci			}
918c2ecf20Sopenharmony_ci			return 0;
928c2ecf20Sopenharmony_ci		}
938c2ecf20Sopenharmony_ci	} else {
948c2ecf20Sopenharmony_ci		struct mount *m;
958c2ecf20Sopenharmony_ci		/*
968c2ecf20Sopenharmony_ci		 * slave 'mnt' to a peer mount that has the
978c2ecf20Sopenharmony_ci		 * same root dentry. If none is available then
988c2ecf20Sopenharmony_ci		 * slave it to anything that is available.
998c2ecf20Sopenharmony_ci		 */
1008c2ecf20Sopenharmony_ci		for (m = master = next_peer(mnt); m != mnt; m = next_peer(m)) {
1018c2ecf20Sopenharmony_ci			if (m->mnt.mnt_root == mnt->mnt.mnt_root) {
1028c2ecf20Sopenharmony_ci				master = m;
1038c2ecf20Sopenharmony_ci				break;
1048c2ecf20Sopenharmony_ci			}
1058c2ecf20Sopenharmony_ci		}
1068c2ecf20Sopenharmony_ci		list_del_init(&mnt->mnt_share);
1078c2ecf20Sopenharmony_ci		mnt->mnt_group_id = 0;
1088c2ecf20Sopenharmony_ci		CLEAR_MNT_SHARED(mnt);
1098c2ecf20Sopenharmony_ci	}
1108c2ecf20Sopenharmony_ci	list_for_each_entry(slave_mnt, &mnt->mnt_slave_list, mnt_slave)
1118c2ecf20Sopenharmony_ci		slave_mnt->mnt_master = master;
1128c2ecf20Sopenharmony_ci	list_move(&mnt->mnt_slave, &master->mnt_slave_list);
1138c2ecf20Sopenharmony_ci	list_splice(&mnt->mnt_slave_list, master->mnt_slave_list.prev);
1148c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&mnt->mnt_slave_list);
1158c2ecf20Sopenharmony_ci	mnt->mnt_master = master;
1168c2ecf20Sopenharmony_ci	return 0;
1178c2ecf20Sopenharmony_ci}
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci/*
1208c2ecf20Sopenharmony_ci * vfsmount lock must be held for write
1218c2ecf20Sopenharmony_ci */
1228c2ecf20Sopenharmony_civoid change_mnt_propagation(struct mount *mnt, int type)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	if (type == MS_SHARED) {
1258c2ecf20Sopenharmony_ci		set_mnt_shared(mnt);
1268c2ecf20Sopenharmony_ci		return;
1278c2ecf20Sopenharmony_ci	}
1288c2ecf20Sopenharmony_ci	do_make_slave(mnt);
1298c2ecf20Sopenharmony_ci	if (type != MS_SLAVE) {
1308c2ecf20Sopenharmony_ci		list_del_init(&mnt->mnt_slave);
1318c2ecf20Sopenharmony_ci		mnt->mnt_master = NULL;
1328c2ecf20Sopenharmony_ci		if (type == MS_UNBINDABLE)
1338c2ecf20Sopenharmony_ci			mnt->mnt.mnt_flags |= MNT_UNBINDABLE;
1348c2ecf20Sopenharmony_ci		else
1358c2ecf20Sopenharmony_ci			mnt->mnt.mnt_flags &= ~MNT_UNBINDABLE;
1368c2ecf20Sopenharmony_ci	}
1378c2ecf20Sopenharmony_ci}
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci/*
1408c2ecf20Sopenharmony_ci * get the next mount in the propagation tree.
1418c2ecf20Sopenharmony_ci * @m: the mount seen last
1428c2ecf20Sopenharmony_ci * @origin: the original mount from where the tree walk initiated
1438c2ecf20Sopenharmony_ci *
1448c2ecf20Sopenharmony_ci * Note that peer groups form contiguous segments of slave lists.
1458c2ecf20Sopenharmony_ci * We rely on that in get_source() to be able to find out if
1468c2ecf20Sopenharmony_ci * vfsmount found while iterating with propagation_next() is
1478c2ecf20Sopenharmony_ci * a peer of one we'd found earlier.
1488c2ecf20Sopenharmony_ci */
1498c2ecf20Sopenharmony_cistatic struct mount *propagation_next(struct mount *m,
1508c2ecf20Sopenharmony_ci					 struct mount *origin)
1518c2ecf20Sopenharmony_ci{
1528c2ecf20Sopenharmony_ci	/* are there any slaves of this mount? */
1538c2ecf20Sopenharmony_ci	if (!IS_MNT_NEW(m) && !list_empty(&m->mnt_slave_list))
1548c2ecf20Sopenharmony_ci		return first_slave(m);
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci	while (1) {
1578c2ecf20Sopenharmony_ci		struct mount *master = m->mnt_master;
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci		if (master == origin->mnt_master) {
1608c2ecf20Sopenharmony_ci			struct mount *next = next_peer(m);
1618c2ecf20Sopenharmony_ci			return (next == origin) ? NULL : next;
1628c2ecf20Sopenharmony_ci		} else if (m->mnt_slave.next != &master->mnt_slave_list)
1638c2ecf20Sopenharmony_ci			return next_slave(m);
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci		/* back at master */
1668c2ecf20Sopenharmony_ci		m = master;
1678c2ecf20Sopenharmony_ci	}
1688c2ecf20Sopenharmony_ci}
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_cistatic struct mount *skip_propagation_subtree(struct mount *m,
1718c2ecf20Sopenharmony_ci						struct mount *origin)
1728c2ecf20Sopenharmony_ci{
1738c2ecf20Sopenharmony_ci	/*
1748c2ecf20Sopenharmony_ci	 * Advance m such that propagation_next will not return
1758c2ecf20Sopenharmony_ci	 * the slaves of m.
1768c2ecf20Sopenharmony_ci	 */
1778c2ecf20Sopenharmony_ci	if (!IS_MNT_NEW(m) && !list_empty(&m->mnt_slave_list))
1788c2ecf20Sopenharmony_ci		m = last_slave(m);
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	return m;
1818c2ecf20Sopenharmony_ci}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_cistatic struct mount *next_group(struct mount *m, struct mount *origin)
1848c2ecf20Sopenharmony_ci{
1858c2ecf20Sopenharmony_ci	while (1) {
1868c2ecf20Sopenharmony_ci		while (1) {
1878c2ecf20Sopenharmony_ci			struct mount *next;
1888c2ecf20Sopenharmony_ci			if (!IS_MNT_NEW(m) && !list_empty(&m->mnt_slave_list))
1898c2ecf20Sopenharmony_ci				return first_slave(m);
1908c2ecf20Sopenharmony_ci			next = next_peer(m);
1918c2ecf20Sopenharmony_ci			if (m->mnt_group_id == origin->mnt_group_id) {
1928c2ecf20Sopenharmony_ci				if (next == origin)
1938c2ecf20Sopenharmony_ci					return NULL;
1948c2ecf20Sopenharmony_ci			} else if (m->mnt_slave.next != &next->mnt_slave)
1958c2ecf20Sopenharmony_ci				break;
1968c2ecf20Sopenharmony_ci			m = next;
1978c2ecf20Sopenharmony_ci		}
1988c2ecf20Sopenharmony_ci		/* m is the last peer */
1998c2ecf20Sopenharmony_ci		while (1) {
2008c2ecf20Sopenharmony_ci			struct mount *master = m->mnt_master;
2018c2ecf20Sopenharmony_ci			if (m->mnt_slave.next != &master->mnt_slave_list)
2028c2ecf20Sopenharmony_ci				return next_slave(m);
2038c2ecf20Sopenharmony_ci			m = next_peer(master);
2048c2ecf20Sopenharmony_ci			if (master->mnt_group_id == origin->mnt_group_id)
2058c2ecf20Sopenharmony_ci				break;
2068c2ecf20Sopenharmony_ci			if (master->mnt_slave.next == &m->mnt_slave)
2078c2ecf20Sopenharmony_ci				break;
2088c2ecf20Sopenharmony_ci			m = master;
2098c2ecf20Sopenharmony_ci		}
2108c2ecf20Sopenharmony_ci		if (m == origin)
2118c2ecf20Sopenharmony_ci			return NULL;
2128c2ecf20Sopenharmony_ci	}
2138c2ecf20Sopenharmony_ci}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci/* all accesses are serialized by namespace_sem */
2168c2ecf20Sopenharmony_cistatic struct mount *last_dest, *first_source, *last_source, *dest_master;
2178c2ecf20Sopenharmony_cistatic struct mountpoint *mp;
2188c2ecf20Sopenharmony_cistatic struct hlist_head *list;
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_cistatic inline bool peers(struct mount *m1, struct mount *m2)
2218c2ecf20Sopenharmony_ci{
2228c2ecf20Sopenharmony_ci	return m1->mnt_group_id == m2->mnt_group_id && m1->mnt_group_id;
2238c2ecf20Sopenharmony_ci}
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_cistatic int propagate_one(struct mount *m)
2268c2ecf20Sopenharmony_ci{
2278c2ecf20Sopenharmony_ci	struct mount *child;
2288c2ecf20Sopenharmony_ci	int type;
2298c2ecf20Sopenharmony_ci	/* skip ones added by this propagate_mnt() */
2308c2ecf20Sopenharmony_ci	if (IS_MNT_NEW(m))
2318c2ecf20Sopenharmony_ci		return 0;
2328c2ecf20Sopenharmony_ci	/* skip if mountpoint isn't covered by it */
2338c2ecf20Sopenharmony_ci	if (!is_subdir(mp->m_dentry, m->mnt.mnt_root))
2348c2ecf20Sopenharmony_ci		return 0;
2358c2ecf20Sopenharmony_ci	if (peers(m, last_dest)) {
2368c2ecf20Sopenharmony_ci		type = CL_MAKE_SHARED;
2378c2ecf20Sopenharmony_ci	} else {
2388c2ecf20Sopenharmony_ci		struct mount *n, *p;
2398c2ecf20Sopenharmony_ci		bool done;
2408c2ecf20Sopenharmony_ci		for (n = m; ; n = p) {
2418c2ecf20Sopenharmony_ci			p = n->mnt_master;
2428c2ecf20Sopenharmony_ci			if (p == dest_master || IS_MNT_MARKED(p))
2438c2ecf20Sopenharmony_ci				break;
2448c2ecf20Sopenharmony_ci		}
2458c2ecf20Sopenharmony_ci		do {
2468c2ecf20Sopenharmony_ci			struct mount *parent = last_source->mnt_parent;
2478c2ecf20Sopenharmony_ci			if (peers(last_source, first_source))
2488c2ecf20Sopenharmony_ci				break;
2498c2ecf20Sopenharmony_ci			done = parent->mnt_master == p;
2508c2ecf20Sopenharmony_ci			if (done && peers(n, parent))
2518c2ecf20Sopenharmony_ci				break;
2528c2ecf20Sopenharmony_ci			last_source = last_source->mnt_master;
2538c2ecf20Sopenharmony_ci		} while (!done);
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci		type = CL_SLAVE;
2568c2ecf20Sopenharmony_ci		/* beginning of peer group among the slaves? */
2578c2ecf20Sopenharmony_ci		if (IS_MNT_SHARED(m))
2588c2ecf20Sopenharmony_ci			type |= CL_MAKE_SHARED;
2598c2ecf20Sopenharmony_ci	}
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	child = copy_tree(last_source, last_source->mnt.mnt_root, type);
2628c2ecf20Sopenharmony_ci	if (IS_ERR(child))
2638c2ecf20Sopenharmony_ci		return PTR_ERR(child);
2648c2ecf20Sopenharmony_ci	read_seqlock_excl(&mount_lock);
2658c2ecf20Sopenharmony_ci	mnt_set_mountpoint(m, mp, child);
2668c2ecf20Sopenharmony_ci	if (m->mnt_master != dest_master)
2678c2ecf20Sopenharmony_ci		SET_MNT_MARK(m->mnt_master);
2688c2ecf20Sopenharmony_ci	read_sequnlock_excl(&mount_lock);
2698c2ecf20Sopenharmony_ci	last_dest = m;
2708c2ecf20Sopenharmony_ci	last_source = child;
2718c2ecf20Sopenharmony_ci	hlist_add_head(&child->mnt_hash, list);
2728c2ecf20Sopenharmony_ci	return count_mounts(m->mnt_ns, child);
2738c2ecf20Sopenharmony_ci}
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci/*
2768c2ecf20Sopenharmony_ci * mount 'source_mnt' under the destination 'dest_mnt' at
2778c2ecf20Sopenharmony_ci * dentry 'dest_dentry'. And propagate that mount to
2788c2ecf20Sopenharmony_ci * all the peer and slave mounts of 'dest_mnt'.
2798c2ecf20Sopenharmony_ci * Link all the new mounts into a propagation tree headed at
2808c2ecf20Sopenharmony_ci * source_mnt. Also link all the new mounts using ->mnt_list
2818c2ecf20Sopenharmony_ci * headed at source_mnt's ->mnt_list
2828c2ecf20Sopenharmony_ci *
2838c2ecf20Sopenharmony_ci * @dest_mnt: destination mount.
2848c2ecf20Sopenharmony_ci * @dest_dentry: destination dentry.
2858c2ecf20Sopenharmony_ci * @source_mnt: source mount.
2868c2ecf20Sopenharmony_ci * @tree_list : list of heads of trees to be attached.
2878c2ecf20Sopenharmony_ci */
2888c2ecf20Sopenharmony_ciint propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp,
2898c2ecf20Sopenharmony_ci		    struct mount *source_mnt, struct hlist_head *tree_list)
2908c2ecf20Sopenharmony_ci{
2918c2ecf20Sopenharmony_ci	struct mount *m, *n;
2928c2ecf20Sopenharmony_ci	int ret = 0;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	/*
2958c2ecf20Sopenharmony_ci	 * we don't want to bother passing tons of arguments to
2968c2ecf20Sopenharmony_ci	 * propagate_one(); everything is serialized by namespace_sem,
2978c2ecf20Sopenharmony_ci	 * so globals will do just fine.
2988c2ecf20Sopenharmony_ci	 */
2998c2ecf20Sopenharmony_ci	last_dest = dest_mnt;
3008c2ecf20Sopenharmony_ci	first_source = source_mnt;
3018c2ecf20Sopenharmony_ci	last_source = source_mnt;
3028c2ecf20Sopenharmony_ci	mp = dest_mp;
3038c2ecf20Sopenharmony_ci	list = tree_list;
3048c2ecf20Sopenharmony_ci	dest_master = dest_mnt->mnt_master;
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	/* all peers of dest_mnt, except dest_mnt itself */
3078c2ecf20Sopenharmony_ci	for (n = next_peer(dest_mnt); n != dest_mnt; n = next_peer(n)) {
3088c2ecf20Sopenharmony_ci		ret = propagate_one(n);
3098c2ecf20Sopenharmony_ci		if (ret)
3108c2ecf20Sopenharmony_ci			goto out;
3118c2ecf20Sopenharmony_ci	}
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	/* all slave groups */
3148c2ecf20Sopenharmony_ci	for (m = next_group(dest_mnt, dest_mnt); m;
3158c2ecf20Sopenharmony_ci			m = next_group(m, dest_mnt)) {
3168c2ecf20Sopenharmony_ci		/* everything in that slave group */
3178c2ecf20Sopenharmony_ci		n = m;
3188c2ecf20Sopenharmony_ci		do {
3198c2ecf20Sopenharmony_ci			ret = propagate_one(n);
3208c2ecf20Sopenharmony_ci			if (ret)
3218c2ecf20Sopenharmony_ci				goto out;
3228c2ecf20Sopenharmony_ci			n = next_peer(n);
3238c2ecf20Sopenharmony_ci		} while (n != m);
3248c2ecf20Sopenharmony_ci	}
3258c2ecf20Sopenharmony_ciout:
3268c2ecf20Sopenharmony_ci	read_seqlock_excl(&mount_lock);
3278c2ecf20Sopenharmony_ci	hlist_for_each_entry(n, tree_list, mnt_hash) {
3288c2ecf20Sopenharmony_ci		m = n->mnt_parent;
3298c2ecf20Sopenharmony_ci		if (m->mnt_master != dest_mnt->mnt_master)
3308c2ecf20Sopenharmony_ci			CLEAR_MNT_MARK(m->mnt_master);
3318c2ecf20Sopenharmony_ci	}
3328c2ecf20Sopenharmony_ci	read_sequnlock_excl(&mount_lock);
3338c2ecf20Sopenharmony_ci	return ret;
3348c2ecf20Sopenharmony_ci}
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_cistatic struct mount *find_topper(struct mount *mnt)
3378c2ecf20Sopenharmony_ci{
3388c2ecf20Sopenharmony_ci	/* If there is exactly one mount covering mnt completely return it. */
3398c2ecf20Sopenharmony_ci	struct mount *child;
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	if (!list_is_singular(&mnt->mnt_mounts))
3428c2ecf20Sopenharmony_ci		return NULL;
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci	child = list_first_entry(&mnt->mnt_mounts, struct mount, mnt_child);
3458c2ecf20Sopenharmony_ci	if (child->mnt_mountpoint != mnt->mnt.mnt_root)
3468c2ecf20Sopenharmony_ci		return NULL;
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	return child;
3498c2ecf20Sopenharmony_ci}
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci/*
3528c2ecf20Sopenharmony_ci * return true if the refcount is greater than count
3538c2ecf20Sopenharmony_ci */
3548c2ecf20Sopenharmony_cistatic inline int do_refcount_check(struct mount *mnt, int count)
3558c2ecf20Sopenharmony_ci{
3568c2ecf20Sopenharmony_ci	return mnt_get_count(mnt) > count;
3578c2ecf20Sopenharmony_ci}
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci/*
3608c2ecf20Sopenharmony_ci * check if the mount 'mnt' can be unmounted successfully.
3618c2ecf20Sopenharmony_ci * @mnt: the mount to be checked for unmount
3628c2ecf20Sopenharmony_ci * NOTE: unmounting 'mnt' would naturally propagate to all
3638c2ecf20Sopenharmony_ci * other mounts its parent propagates to.
3648c2ecf20Sopenharmony_ci * Check if any of these mounts that **do not have submounts**
3658c2ecf20Sopenharmony_ci * have more references than 'refcnt'. If so return busy.
3668c2ecf20Sopenharmony_ci *
3678c2ecf20Sopenharmony_ci * vfsmount lock must be held for write
3688c2ecf20Sopenharmony_ci */
3698c2ecf20Sopenharmony_ciint propagate_mount_busy(struct mount *mnt, int refcnt)
3708c2ecf20Sopenharmony_ci{
3718c2ecf20Sopenharmony_ci	struct mount *m, *child, *topper;
3728c2ecf20Sopenharmony_ci	struct mount *parent = mnt->mnt_parent;
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	if (mnt == parent)
3758c2ecf20Sopenharmony_ci		return do_refcount_check(mnt, refcnt);
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	/*
3788c2ecf20Sopenharmony_ci	 * quickly check if the current mount can be unmounted.
3798c2ecf20Sopenharmony_ci	 * If not, we don't have to go checking for all other
3808c2ecf20Sopenharmony_ci	 * mounts
3818c2ecf20Sopenharmony_ci	 */
3828c2ecf20Sopenharmony_ci	if (!list_empty(&mnt->mnt_mounts) || do_refcount_check(mnt, refcnt))
3838c2ecf20Sopenharmony_ci		return 1;
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	for (m = propagation_next(parent, parent); m;
3868c2ecf20Sopenharmony_ci	     		m = propagation_next(m, parent)) {
3878c2ecf20Sopenharmony_ci		int count = 1;
3888c2ecf20Sopenharmony_ci		child = __lookup_mnt(&m->mnt, mnt->mnt_mountpoint);
3898c2ecf20Sopenharmony_ci		if (!child)
3908c2ecf20Sopenharmony_ci			continue;
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci		/* Is there exactly one mount on the child that covers
3938c2ecf20Sopenharmony_ci		 * it completely whose reference should be ignored?
3948c2ecf20Sopenharmony_ci		 */
3958c2ecf20Sopenharmony_ci		topper = find_topper(child);
3968c2ecf20Sopenharmony_ci		if (topper)
3978c2ecf20Sopenharmony_ci			count += 1;
3988c2ecf20Sopenharmony_ci		else if (!list_empty(&child->mnt_mounts))
3998c2ecf20Sopenharmony_ci			continue;
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci		if (do_refcount_check(child, count))
4028c2ecf20Sopenharmony_ci			return 1;
4038c2ecf20Sopenharmony_ci	}
4048c2ecf20Sopenharmony_ci	return 0;
4058c2ecf20Sopenharmony_ci}
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci/*
4088c2ecf20Sopenharmony_ci * Clear MNT_LOCKED when it can be shown to be safe.
4098c2ecf20Sopenharmony_ci *
4108c2ecf20Sopenharmony_ci * mount_lock lock must be held for write
4118c2ecf20Sopenharmony_ci */
4128c2ecf20Sopenharmony_civoid propagate_mount_unlock(struct mount *mnt)
4138c2ecf20Sopenharmony_ci{
4148c2ecf20Sopenharmony_ci	struct mount *parent = mnt->mnt_parent;
4158c2ecf20Sopenharmony_ci	struct mount *m, *child;
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	BUG_ON(parent == mnt);
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	for (m = propagation_next(parent, parent); m;
4208c2ecf20Sopenharmony_ci			m = propagation_next(m, parent)) {
4218c2ecf20Sopenharmony_ci		child = __lookup_mnt(&m->mnt, mnt->mnt_mountpoint);
4228c2ecf20Sopenharmony_ci		if (child)
4238c2ecf20Sopenharmony_ci			child->mnt.mnt_flags &= ~MNT_LOCKED;
4248c2ecf20Sopenharmony_ci	}
4258c2ecf20Sopenharmony_ci}
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_cistatic void umount_one(struct mount *mnt, struct list_head *to_umount)
4288c2ecf20Sopenharmony_ci{
4298c2ecf20Sopenharmony_ci	CLEAR_MNT_MARK(mnt);
4308c2ecf20Sopenharmony_ci	mnt->mnt.mnt_flags |= MNT_UMOUNT;
4318c2ecf20Sopenharmony_ci	list_del_init(&mnt->mnt_child);
4328c2ecf20Sopenharmony_ci	list_del_init(&mnt->mnt_umounting);
4338c2ecf20Sopenharmony_ci	list_move_tail(&mnt->mnt_list, to_umount);
4348c2ecf20Sopenharmony_ci}
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci/*
4378c2ecf20Sopenharmony_ci * NOTE: unmounting 'mnt' naturally propagates to all other mounts its
4388c2ecf20Sopenharmony_ci * parent propagates to.
4398c2ecf20Sopenharmony_ci */
4408c2ecf20Sopenharmony_cistatic bool __propagate_umount(struct mount *mnt,
4418c2ecf20Sopenharmony_ci			       struct list_head *to_umount,
4428c2ecf20Sopenharmony_ci			       struct list_head *to_restore)
4438c2ecf20Sopenharmony_ci{
4448c2ecf20Sopenharmony_ci	bool progress = false;
4458c2ecf20Sopenharmony_ci	struct mount *child;
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci	/*
4488c2ecf20Sopenharmony_ci	 * The state of the parent won't change if this mount is
4498c2ecf20Sopenharmony_ci	 * already unmounted or marked as without children.
4508c2ecf20Sopenharmony_ci	 */
4518c2ecf20Sopenharmony_ci	if (mnt->mnt.mnt_flags & (MNT_UMOUNT | MNT_MARKED))
4528c2ecf20Sopenharmony_ci		goto out;
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	/* Verify topper is the only grandchild that has not been
4558c2ecf20Sopenharmony_ci	 * speculatively unmounted.
4568c2ecf20Sopenharmony_ci	 */
4578c2ecf20Sopenharmony_ci	list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) {
4588c2ecf20Sopenharmony_ci		if (child->mnt_mountpoint == mnt->mnt.mnt_root)
4598c2ecf20Sopenharmony_ci			continue;
4608c2ecf20Sopenharmony_ci		if (!list_empty(&child->mnt_umounting) && IS_MNT_MARKED(child))
4618c2ecf20Sopenharmony_ci			continue;
4628c2ecf20Sopenharmony_ci		/* Found a mounted child */
4638c2ecf20Sopenharmony_ci		goto children;
4648c2ecf20Sopenharmony_ci	}
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci	/* Mark mounts that can be unmounted if not locked */
4678c2ecf20Sopenharmony_ci	SET_MNT_MARK(mnt);
4688c2ecf20Sopenharmony_ci	progress = true;
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci	/* If a mount is without children and not locked umount it. */
4718c2ecf20Sopenharmony_ci	if (!IS_MNT_LOCKED(mnt)) {
4728c2ecf20Sopenharmony_ci		umount_one(mnt, to_umount);
4738c2ecf20Sopenharmony_ci	} else {
4748c2ecf20Sopenharmony_cichildren:
4758c2ecf20Sopenharmony_ci		list_move_tail(&mnt->mnt_umounting, to_restore);
4768c2ecf20Sopenharmony_ci	}
4778c2ecf20Sopenharmony_ciout:
4788c2ecf20Sopenharmony_ci	return progress;
4798c2ecf20Sopenharmony_ci}
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_cistatic void umount_list(struct list_head *to_umount,
4828c2ecf20Sopenharmony_ci			struct list_head *to_restore)
4838c2ecf20Sopenharmony_ci{
4848c2ecf20Sopenharmony_ci	struct mount *mnt, *child, *tmp;
4858c2ecf20Sopenharmony_ci	list_for_each_entry(mnt, to_umount, mnt_list) {
4868c2ecf20Sopenharmony_ci		list_for_each_entry_safe(child, tmp, &mnt->mnt_mounts, mnt_child) {
4878c2ecf20Sopenharmony_ci			/* topper? */
4888c2ecf20Sopenharmony_ci			if (child->mnt_mountpoint == mnt->mnt.mnt_root)
4898c2ecf20Sopenharmony_ci				list_move_tail(&child->mnt_umounting, to_restore);
4908c2ecf20Sopenharmony_ci			else
4918c2ecf20Sopenharmony_ci				umount_one(child, to_umount);
4928c2ecf20Sopenharmony_ci		}
4938c2ecf20Sopenharmony_ci	}
4948c2ecf20Sopenharmony_ci}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_cistatic void restore_mounts(struct list_head *to_restore)
4978c2ecf20Sopenharmony_ci{
4988c2ecf20Sopenharmony_ci	/* Restore mounts to a clean working state */
4998c2ecf20Sopenharmony_ci	while (!list_empty(to_restore)) {
5008c2ecf20Sopenharmony_ci		struct mount *mnt, *parent;
5018c2ecf20Sopenharmony_ci		struct mountpoint *mp;
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci		mnt = list_first_entry(to_restore, struct mount, mnt_umounting);
5048c2ecf20Sopenharmony_ci		CLEAR_MNT_MARK(mnt);
5058c2ecf20Sopenharmony_ci		list_del_init(&mnt->mnt_umounting);
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci		/* Should this mount be reparented? */
5088c2ecf20Sopenharmony_ci		mp = mnt->mnt_mp;
5098c2ecf20Sopenharmony_ci		parent = mnt->mnt_parent;
5108c2ecf20Sopenharmony_ci		while (parent->mnt.mnt_flags & MNT_UMOUNT) {
5118c2ecf20Sopenharmony_ci			mp = parent->mnt_mp;
5128c2ecf20Sopenharmony_ci			parent = parent->mnt_parent;
5138c2ecf20Sopenharmony_ci		}
5148c2ecf20Sopenharmony_ci		if (parent != mnt->mnt_parent)
5158c2ecf20Sopenharmony_ci			mnt_change_mountpoint(parent, mp, mnt);
5168c2ecf20Sopenharmony_ci	}
5178c2ecf20Sopenharmony_ci}
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_cistatic void cleanup_umount_visitations(struct list_head *visited)
5208c2ecf20Sopenharmony_ci{
5218c2ecf20Sopenharmony_ci	while (!list_empty(visited)) {
5228c2ecf20Sopenharmony_ci		struct mount *mnt =
5238c2ecf20Sopenharmony_ci			list_first_entry(visited, struct mount, mnt_umounting);
5248c2ecf20Sopenharmony_ci		list_del_init(&mnt->mnt_umounting);
5258c2ecf20Sopenharmony_ci	}
5268c2ecf20Sopenharmony_ci}
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci/*
5298c2ecf20Sopenharmony_ci * collect all mounts that receive propagation from the mount in @list,
5308c2ecf20Sopenharmony_ci * and return these additional mounts in the same list.
5318c2ecf20Sopenharmony_ci * @list: the list of mounts to be unmounted.
5328c2ecf20Sopenharmony_ci *
5338c2ecf20Sopenharmony_ci * vfsmount lock must be held for write
5348c2ecf20Sopenharmony_ci */
5358c2ecf20Sopenharmony_ciint propagate_umount(struct list_head *list)
5368c2ecf20Sopenharmony_ci{
5378c2ecf20Sopenharmony_ci	struct mount *mnt;
5388c2ecf20Sopenharmony_ci	LIST_HEAD(to_restore);
5398c2ecf20Sopenharmony_ci	LIST_HEAD(to_umount);
5408c2ecf20Sopenharmony_ci	LIST_HEAD(visited);
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci	/* Find candidates for unmounting */
5438c2ecf20Sopenharmony_ci	list_for_each_entry_reverse(mnt, list, mnt_list) {
5448c2ecf20Sopenharmony_ci		struct mount *parent = mnt->mnt_parent;
5458c2ecf20Sopenharmony_ci		struct mount *m;
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci		/*
5488c2ecf20Sopenharmony_ci		 * If this mount has already been visited it is known that it's
5498c2ecf20Sopenharmony_ci		 * entire peer group and all of their slaves in the propagation
5508c2ecf20Sopenharmony_ci		 * tree for the mountpoint has already been visited and there is
5518c2ecf20Sopenharmony_ci		 * no need to visit them again.
5528c2ecf20Sopenharmony_ci		 */
5538c2ecf20Sopenharmony_ci		if (!list_empty(&mnt->mnt_umounting))
5548c2ecf20Sopenharmony_ci			continue;
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci		list_add_tail(&mnt->mnt_umounting, &visited);
5578c2ecf20Sopenharmony_ci		for (m = propagation_next(parent, parent); m;
5588c2ecf20Sopenharmony_ci		     m = propagation_next(m, parent)) {
5598c2ecf20Sopenharmony_ci			struct mount *child = __lookup_mnt(&m->mnt,
5608c2ecf20Sopenharmony_ci							   mnt->mnt_mountpoint);
5618c2ecf20Sopenharmony_ci			if (!child)
5628c2ecf20Sopenharmony_ci				continue;
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci			if (!list_empty(&child->mnt_umounting)) {
5658c2ecf20Sopenharmony_ci				/*
5668c2ecf20Sopenharmony_ci				 * If the child has already been visited it is
5678c2ecf20Sopenharmony_ci				 * know that it's entire peer group and all of
5688c2ecf20Sopenharmony_ci				 * their slaves in the propgation tree for the
5698c2ecf20Sopenharmony_ci				 * mountpoint has already been visited and there
5708c2ecf20Sopenharmony_ci				 * is no need to visit this subtree again.
5718c2ecf20Sopenharmony_ci				 */
5728c2ecf20Sopenharmony_ci				m = skip_propagation_subtree(m, parent);
5738c2ecf20Sopenharmony_ci				continue;
5748c2ecf20Sopenharmony_ci			} else if (child->mnt.mnt_flags & MNT_UMOUNT) {
5758c2ecf20Sopenharmony_ci				/*
5768c2ecf20Sopenharmony_ci				 * We have come accross an partially unmounted
5778c2ecf20Sopenharmony_ci				 * mount in list that has not been visited yet.
5788c2ecf20Sopenharmony_ci				 * Remember it has been visited and continue
5798c2ecf20Sopenharmony_ci				 * about our merry way.
5808c2ecf20Sopenharmony_ci				 */
5818c2ecf20Sopenharmony_ci				list_add_tail(&child->mnt_umounting, &visited);
5828c2ecf20Sopenharmony_ci				continue;
5838c2ecf20Sopenharmony_ci			}
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci			/* Check the child and parents while progress is made */
5868c2ecf20Sopenharmony_ci			while (__propagate_umount(child,
5878c2ecf20Sopenharmony_ci						  &to_umount, &to_restore)) {
5888c2ecf20Sopenharmony_ci				/* Is the parent a umount candidate? */
5898c2ecf20Sopenharmony_ci				child = child->mnt_parent;
5908c2ecf20Sopenharmony_ci				if (list_empty(&child->mnt_umounting))
5918c2ecf20Sopenharmony_ci					break;
5928c2ecf20Sopenharmony_ci			}
5938c2ecf20Sopenharmony_ci		}
5948c2ecf20Sopenharmony_ci	}
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	umount_list(&to_umount, &to_restore);
5978c2ecf20Sopenharmony_ci	restore_mounts(&to_restore);
5988c2ecf20Sopenharmony_ci	cleanup_umount_visitations(&visited);
5998c2ecf20Sopenharmony_ci	list_splice_tail(&to_umount, list);
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci	return 0;
6028c2ecf20Sopenharmony_ci}
603