162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#include <linux/mount.h>
362306a36Sopenharmony_ci#include <linux/seq_file.h>
462306a36Sopenharmony_ci#include <linux/poll.h>
562306a36Sopenharmony_ci#include <linux/ns_common.h>
662306a36Sopenharmony_ci#include <linux/fs_pin.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_cistruct mnt_namespace {
962306a36Sopenharmony_ci	struct ns_common	ns;
1062306a36Sopenharmony_ci	struct mount *	root;
1162306a36Sopenharmony_ci	/*
1262306a36Sopenharmony_ci	 * Traversal and modification of .list is protected by either
1362306a36Sopenharmony_ci	 * - taking namespace_sem for write, OR
1462306a36Sopenharmony_ci	 * - taking namespace_sem for read AND taking .ns_lock.
1562306a36Sopenharmony_ci	 */
1662306a36Sopenharmony_ci	struct list_head	list;
1762306a36Sopenharmony_ci	spinlock_t		ns_lock;
1862306a36Sopenharmony_ci	struct user_namespace	*user_ns;
1962306a36Sopenharmony_ci	struct ucounts		*ucounts;
2062306a36Sopenharmony_ci	u64			seq;	/* Sequence number to prevent loops */
2162306a36Sopenharmony_ci	wait_queue_head_t poll;
2262306a36Sopenharmony_ci	u64 event;
2362306a36Sopenharmony_ci	unsigned int		mounts; /* # of mounts in the namespace */
2462306a36Sopenharmony_ci	unsigned int		pending_mounts;
2562306a36Sopenharmony_ci} __randomize_layout;
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cistruct mnt_pcp {
2862306a36Sopenharmony_ci	int mnt_count;
2962306a36Sopenharmony_ci	int mnt_writers;
3062306a36Sopenharmony_ci};
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_cistruct mountpoint {
3362306a36Sopenharmony_ci	struct hlist_node m_hash;
3462306a36Sopenharmony_ci	struct dentry *m_dentry;
3562306a36Sopenharmony_ci	struct hlist_head m_list;
3662306a36Sopenharmony_ci	int m_count;
3762306a36Sopenharmony_ci};
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_cistruct mount {
4062306a36Sopenharmony_ci	struct hlist_node mnt_hash;
4162306a36Sopenharmony_ci	struct mount *mnt_parent;
4262306a36Sopenharmony_ci	struct dentry *mnt_mountpoint;
4362306a36Sopenharmony_ci	struct vfsmount mnt;
4462306a36Sopenharmony_ci	union {
4562306a36Sopenharmony_ci		struct rcu_head mnt_rcu;
4662306a36Sopenharmony_ci		struct llist_node mnt_llist;
4762306a36Sopenharmony_ci	};
4862306a36Sopenharmony_ci#ifdef CONFIG_SMP
4962306a36Sopenharmony_ci	struct mnt_pcp __percpu *mnt_pcp;
5062306a36Sopenharmony_ci#else
5162306a36Sopenharmony_ci	int mnt_count;
5262306a36Sopenharmony_ci	int mnt_writers;
5362306a36Sopenharmony_ci#endif
5462306a36Sopenharmony_ci	struct list_head mnt_mounts;	/* list of children, anchored here */
5562306a36Sopenharmony_ci	struct list_head mnt_child;	/* and going through their mnt_child */
5662306a36Sopenharmony_ci	struct list_head mnt_instance;	/* mount instance on sb->s_mounts */
5762306a36Sopenharmony_ci	const char *mnt_devname;	/* Name of device e.g. /dev/dsk/hda1 */
5862306a36Sopenharmony_ci	struct list_head mnt_list;
5962306a36Sopenharmony_ci	struct list_head mnt_expire;	/* link in fs-specific expiry list */
6062306a36Sopenharmony_ci	struct list_head mnt_share;	/* circular list of shared mounts */
6162306a36Sopenharmony_ci	struct list_head mnt_slave_list;/* list of slave mounts */
6262306a36Sopenharmony_ci	struct list_head mnt_slave;	/* slave list entry */
6362306a36Sopenharmony_ci	struct mount *mnt_master;	/* slave is on master->mnt_slave_list */
6462306a36Sopenharmony_ci	struct mnt_namespace *mnt_ns;	/* containing namespace */
6562306a36Sopenharmony_ci	struct mountpoint *mnt_mp;	/* where is it mounted */
6662306a36Sopenharmony_ci	union {
6762306a36Sopenharmony_ci		struct hlist_node mnt_mp_list;	/* list mounts with the same mountpoint */
6862306a36Sopenharmony_ci		struct hlist_node mnt_umount;
6962306a36Sopenharmony_ci	};
7062306a36Sopenharmony_ci	struct list_head mnt_umounting; /* list entry for umount propagation */
7162306a36Sopenharmony_ci#ifdef CONFIG_FSNOTIFY
7262306a36Sopenharmony_ci	struct fsnotify_mark_connector __rcu *mnt_fsnotify_marks;
7362306a36Sopenharmony_ci	__u32 mnt_fsnotify_mask;
7462306a36Sopenharmony_ci#endif
7562306a36Sopenharmony_ci	int mnt_id;			/* mount identifier */
7662306a36Sopenharmony_ci	int mnt_group_id;		/* peer group identifier */
7762306a36Sopenharmony_ci	int mnt_expiry_mark;		/* true if marked for expiry */
7862306a36Sopenharmony_ci	struct hlist_head mnt_pins;
7962306a36Sopenharmony_ci	struct hlist_head mnt_stuck_children;
8062306a36Sopenharmony_ci} __randomize_layout;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci#define MNT_NS_INTERNAL ERR_PTR(-EINVAL) /* distinct from any mnt_namespace */
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_cistatic inline struct mount *real_mount(struct vfsmount *mnt)
8562306a36Sopenharmony_ci{
8662306a36Sopenharmony_ci	return container_of(mnt, struct mount, mnt);
8762306a36Sopenharmony_ci}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cistatic inline int mnt_has_parent(struct mount *mnt)
9062306a36Sopenharmony_ci{
9162306a36Sopenharmony_ci	return mnt != mnt->mnt_parent;
9262306a36Sopenharmony_ci}
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistatic inline int is_mounted(struct vfsmount *mnt)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	/* neither detached nor internal? */
9762306a36Sopenharmony_ci	return !IS_ERR_OR_NULL(real_mount(mnt)->mnt_ns);
9862306a36Sopenharmony_ci}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ciextern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *);
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ciextern int __legitimize_mnt(struct vfsmount *, unsigned);
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cistatic inline bool __path_is_mountpoint(const struct path *path)
10562306a36Sopenharmony_ci{
10662306a36Sopenharmony_ci	struct mount *m = __lookup_mnt(path->mnt, path->dentry);
10762306a36Sopenharmony_ci	return m && likely(!(m->mnt.mnt_flags & MNT_SYNC_UMOUNT));
10862306a36Sopenharmony_ci}
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ciextern void __detach_mounts(struct dentry *dentry);
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_cistatic inline void detach_mounts(struct dentry *dentry)
11362306a36Sopenharmony_ci{
11462306a36Sopenharmony_ci	if (!d_mountpoint(dentry))
11562306a36Sopenharmony_ci		return;
11662306a36Sopenharmony_ci	__detach_mounts(dentry);
11762306a36Sopenharmony_ci}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_cistatic inline void get_mnt_ns(struct mnt_namespace *ns)
12062306a36Sopenharmony_ci{
12162306a36Sopenharmony_ci	refcount_inc(&ns->ns.count);
12262306a36Sopenharmony_ci}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ciextern seqlock_t mount_lock;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_cistruct proc_mounts {
12762306a36Sopenharmony_ci	struct mnt_namespace *ns;
12862306a36Sopenharmony_ci	struct path root;
12962306a36Sopenharmony_ci	int (*show)(struct seq_file *, struct vfsmount *);
13062306a36Sopenharmony_ci	struct mount cursor;
13162306a36Sopenharmony_ci};
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ciextern const struct seq_operations mounts_op;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ciextern bool __is_local_mountpoint(struct dentry *dentry);
13662306a36Sopenharmony_cistatic inline bool is_local_mountpoint(struct dentry *dentry)
13762306a36Sopenharmony_ci{
13862306a36Sopenharmony_ci	if (!d_mountpoint(dentry))
13962306a36Sopenharmony_ci		return false;
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	return __is_local_mountpoint(dentry);
14262306a36Sopenharmony_ci}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_cistatic inline bool is_anon_ns(struct mnt_namespace *ns)
14562306a36Sopenharmony_ci{
14662306a36Sopenharmony_ci	return ns->seq == 0;
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ciextern void mnt_cursor_del(struct mnt_namespace *ns, struct mount *cursor);
150