Miklos Szerediproc/mounts: add cursor9f6c61f6 years agoHistory
161 lines · 4.2 KB · C
RawDownload
/* SPDX-License-Identifier: GPL-2.0 */#include <linux/mount.h>#include <linux/seq_file.h>#include <linux/poll.h>#include <linux/ns_common.h>#include <linux/fs_pin.h> struct mnt_namespace {	atomic_t		count;	struct ns_common	ns;	struct mount *	root;	/*	 * Traversal and modification of .list is protected by either	 * - taking namespace_sem for write, OR	 * - taking namespace_sem for read AND taking .ns_lock.	 */	struct list_head	list;	spinlock_t		ns_lock;	struct user_namespace	*user_ns;	struct ucounts		*ucounts;	u64			seq;	/* Sequence number to prevent loops */	wait_queue_head_t poll;	u64 event;	unsigned int		mounts; /* # of mounts in the namespace */	unsigned int		pending_mounts;} __randomize_layout; struct mnt_pcp {	int mnt_count;	int mnt_writers;}; struct mountpoint {	struct hlist_node m_hash;	struct dentry *m_dentry;	struct hlist_head m_list;	int m_count;}; struct mount {	struct hlist_node mnt_hash;	struct mount *mnt_parent;	struct dentry *mnt_mountpoint;	struct vfsmount mnt;	union {		struct rcu_head mnt_rcu;		struct llist_node mnt_llist;	};#ifdef CONFIG_SMP	struct mnt_pcp __percpu *mnt_pcp;#else	int mnt_count;	int mnt_writers;#endif	struct list_head mnt_mounts;	/* list of children, anchored here */	struct list_head mnt_child;	/* and going through their mnt_child */	struct list_head mnt_instance;	/* mount instance on sb->s_mounts */	const char *mnt_devname;	/* Name of device e.g. /dev/dsk/hda1 */	struct list_head mnt_list;	struct list_head mnt_expire;	/* link in fs-specific expiry list */	struct list_head mnt_share;	/* circular list of shared mounts */	struct list_head mnt_slave_list;/* list of slave mounts */	struct list_head mnt_slave;	/* slave list entry */	struct mount *mnt_master;	/* slave is on master->mnt_slave_list */	struct mnt_namespace *mnt_ns;	/* containing namespace */	struct mountpoint *mnt_mp;	/* where is it mounted */	union {		struct hlist_node mnt_mp_list;	/* list mounts with the same mountpoint */		struct hlist_node mnt_umount;	};	struct list_head mnt_umounting; /* list entry for umount propagation */#ifdef CONFIG_FSNOTIFY	struct fsnotify_mark_connector __rcu *mnt_fsnotify_marks;	__u32 mnt_fsnotify_mask;#endif	int mnt_id;			/* mount identifier */	int mnt_group_id;		/* peer group identifier */	int mnt_expiry_mark;		/* true if marked for expiry */	struct hlist_head mnt_pins;	struct hlist_head mnt_stuck_children;} __randomize_layout; #define MNT_NS_INTERNAL ERR_PTR(-EINVAL) /* distinct from any mnt_namespace */ static inline struct mount *real_mount(struct vfsmount *mnt){	return container_of(mnt, struct mount, mnt);} static inline int mnt_has_parent(struct mount *mnt){	return mnt != mnt->mnt_parent;} static inline int is_mounted(struct vfsmount *mnt){	/* neither detached nor internal? */	return !IS_ERR_OR_NULL(real_mount(mnt)->mnt_ns);} extern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *); extern int __legitimize_mnt(struct vfsmount *, unsigned);extern bool legitimize_mnt(struct vfsmount *, unsigned); static inline bool __path_is_mountpoint(const struct path *path){	struct mount *m = __lookup_mnt(path->mnt, path->dentry);	return m && likely(!(m->mnt.mnt_flags & MNT_SYNC_UMOUNT));} extern void __detach_mounts(struct dentry *dentry); static inline void detach_mounts(struct dentry *dentry){	if (!d_mountpoint(dentry))		return;	__detach_mounts(dentry);} static inline void get_mnt_ns(struct mnt_namespace *ns){	atomic_inc(&ns->count);} extern seqlock_t mount_lock; static inline void lock_mount_hash(void){	write_seqlock(&mount_lock);} static inline void unlock_mount_hash(void){	write_sequnlock(&mount_lock);} struct proc_mounts {	struct mnt_namespace *ns;	struct path root;	int (*show)(struct seq_file *, struct vfsmount *);	struct mount cursor;}; extern const struct seq_operations mounts_op; extern bool __is_local_mountpoint(struct dentry *dentry);static inline bool is_local_mountpoint(struct dentry *dentry){	if (!d_mountpoint(dentry))		return false; 	return __is_local_mountpoint(dentry);} static inline bool is_anon_ns(struct mnt_namespace *ns){	return ns->seq == 0;} extern void mnt_cursor_del(struct mnt_namespace *ns, struct mount *cursor);