Files

267 lines
7.5 KiB
C
Raw Permalink Normal View History

/* 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>
2026-01-12 16:47:10 +01:00
extern struct file_system_type nullfs_fs_type;
extern struct list_head notify_list;
struct mnt_namespace {
struct ns_common ns;
2011-12-06 13:32:36 -05:00
struct mount * root;
2024-12-15 21:17:06 +01:00
struct {
struct rb_root mounts; /* Protected by namespace_sem */
struct rb_node *mnt_last_node; /* last (rightmost) mount in the rbtree */
struct rb_node *mnt_first_node; /* first (leftmost) mount in the rbtree */
};
struct user_namespace *user_ns;
struct ucounts *ucounts;
2025-09-12 13:52:41 +02:00
wait_queue_head_t poll;
u64 seq_origin; /* Sequence number of origin mount namespace */
2014-02-27 14:40:10 -05:00
u64 event;
#ifdef CONFIG_FSNOTIFY
__u32 n_fsnotify_mask;
struct fsnotify_mark_connector __rcu *n_fsnotify_marks;
#endif
2023-10-25 16:02:00 +02:00
unsigned int nr_mounts; /* # of mounts in the namespace */
unsigned int pending_mounts;
refcount_t passive; /* number references not pinning @mounts */
bool is_anon;
} __randomize_layout;
2011-11-24 22:53:09 -05:00
struct mnt_pcp {
int mnt_count;
int mnt_writers;
};
struct mountpoint {
2014-02-28 13:46:44 -05:00
struct hlist_node m_hash;
struct dentry *m_dentry;
2013-09-22 19:37:01 -07:00
struct hlist_head m_list;
};
2011-11-23 12:14:10 -05:00
struct mount {
2014-03-20 21:10:51 -04:00
struct hlist_node mnt_hash;
struct mount *mnt_parent;
2011-11-24 22:25:07 -05:00
struct dentry *mnt_mountpoint;
2011-11-23 12:14:10 -05:00
struct vfsmount mnt;
2014-08-08 13:08:20 -04:00
union {
2024-12-15 21:17:05 +01:00
struct rb_node mnt_node; /* node in the ns->mounts rbtree */
2014-08-08 13:08:20 -04:00
struct rcu_head mnt_rcu;
struct llist_node mnt_llist;
};
2011-11-24 22:53:09 -05:00
#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 mount *mnt_next_for_sb; /* the next two fields are hlist_node, */
struct mount * __aligned(1) *mnt_pprev_for_sb;
2025-08-27 13:37:12 -04:00
/* except that LSB of pprev is stolen */
#define WRITE_HOLD 1 /* ... for use by mnt_hold_writers() */
2011-11-25 02:25:17 -05:00
const char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */
2024-12-15 21:17:05 +01:00
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 hlist_head mnt_slave_list;/* list of slave mounts */
struct hlist_node mnt_slave; /* slave list entry */
struct mount *mnt_master; /* slave is on master->mnt_slave_list */
2011-11-25 00:46:35 -05:00
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;
};
2011-11-25 02:35:16 -05:00
#ifdef CONFIG_FSNOTIFY
struct fsnotify_mark_connector __rcu *mnt_fsnotify_marks;
2011-11-25 02:35:16 -05:00
__u32 mnt_fsnotify_mask;
struct list_head to_notify; /* need to queue notification */
struct mnt_namespace *prev_ns; /* previous namespace (NULL if none) */
2011-11-25 02:35:16 -05:00
#endif
int mnt_t_flags; /* namespace_sem-protected flags */
2023-10-25 16:01:59 +02:00
int mnt_id; /* mount identifier, reused */
u64 mnt_id_unique; /* mount ID unique until reboot */
2011-11-25 00:50:41 -05:00
int mnt_group_id; /* peer group identifier */
int mnt_expiry_mark; /* true if marked for expiry */
2014-08-07 06:23:41 -04:00
struct hlist_head mnt_pins;
struct hlist_head mnt_stuck_children;
2025-06-20 22:46:55 -04:00
struct mount *overmount; /* mounted on ->mnt_root */
} __randomize_layout;
2011-11-23 12:14:10 -05:00
enum {
T_SHARED = 1, /* mount is shared */
T_UNBINDABLE = 2, /* mount is unbindable */
T_MARKED = 4, /* internal mark for propagate_... */
T_UMOUNT_CANDIDATE = 8, /* for propagate_umount */
/*
* T_SHARED_MASK is the set of flags that should be cleared when a
* mount becomes shared. Currently, this is only the flag that says a
* mount cannot be bind mounted, since this is how we create a mount
* that shares events with another mount. If you add a new T_*
* flag, consider how it interacts with shared mounts.
*/
T_SHARED_MASK = T_UNBINDABLE,
};
2012-06-09 00:59:08 -04:00
#define MNT_NS_INTERNAL ERR_PTR(-EINVAL) /* distinct from any mnt_namespace */
2011-11-23 12:14:10 -05:00
static inline struct mount *real_mount(struct vfsmount *mnt)
{
return container_of(mnt, struct mount, mnt);
}
2025-04-28 21:48:45 -04:00
static inline int mnt_has_parent(const struct mount *mnt)
{
return mnt != mnt->mnt_parent;
}
2012-06-09 00:59:08 -04:00
static inline int is_mounted(struct vfsmount *mnt)
{
/* neither detached nor internal? */
return !IS_ERR_OR_NULL(real_mount(mnt)->mnt_ns);
2012-06-09 00:59:08 -04:00
}
2013-10-01 16:11:26 -04:00
extern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *);
2015-05-08 11:43:53 -04:00
extern int __legitimize_mnt(struct vfsmount *, unsigned);
2013-09-29 22:06:07 -04:00
2016-11-24 08:03:41 +11:00
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)
{
2025-09-18 12:11:47 +02:00
ns_ref_inc(ns);
}
2013-09-29 22:06:07 -04:00
extern seqlock_t mount_lock;
2025-08-20 19:54:45 -04:00
DEFINE_LOCK_GUARD_0(mount_writer, write_seqlock(&mount_lock),
write_sequnlock(&mount_lock))
DEFINE_LOCK_GUARD_0(mount_locked_reader, read_seqlock_excl(&mount_lock),
read_sequnlock_excl(&mount_lock))
struct proc_mounts {
struct mnt_namespace *ns;
struct path root;
int (*show)(struct seq_file *, struct vfsmount *);
};
extern const struct seq_operations mounts_op;
2025-06-09 22:03:17 -04:00
extern bool __is_local_mountpoint(const struct dentry *dentry);
static inline bool is_local_mountpoint(const struct dentry *dentry)
{
if (!d_mountpoint(dentry))
return false;
return __is_local_mountpoint(dentry);
}
2019-01-30 13:30:21 -05:00
static inline bool is_anon_ns(struct mnt_namespace *ns)
{
return ns->is_anon;
2019-01-30 13:30:21 -05:00
}
2020-05-14 16:44:24 +02:00
2025-06-08 23:25:36 -04:00
static inline bool anon_ns_root(const struct mount *m)
{
struct mnt_namespace *ns = READ_ONCE(m->mnt_ns);
return !IS_ERR_OR_NULL(ns) && is_anon_ns(ns) && m == ns->root;
}
2024-12-15 21:17:05 +01:00
static inline bool mnt_ns_attached(const struct mount *mnt)
{
return !RB_EMPTY_NODE(&mnt->mnt_node);
}
2025-02-21 14:13:01 +01:00
static inline bool mnt_ns_empty(const struct mnt_namespace *ns)
{
return RB_EMPTY_ROOT(&ns->mounts);
}
static inline void move_from_ns(struct mount *mnt)
2023-10-25 16:02:00 +02:00
{
2024-12-15 21:17:06 +01:00
struct mnt_namespace *ns = mnt->mnt_ns;
2024-12-15 21:17:05 +01:00
WARN_ON(!mnt_ns_attached(mnt));
2024-12-15 21:17:06 +01:00
if (ns->mnt_last_node == &mnt->mnt_node)
ns->mnt_last_node = rb_prev(&mnt->mnt_node);
if (ns->mnt_first_node == &mnt->mnt_node)
ns->mnt_first_node = rb_next(&mnt->mnt_node);
rb_erase(&mnt->mnt_node, &ns->mounts);
2024-12-15 21:17:05 +01:00
RB_CLEAR_NODE(&mnt->mnt_node);
2023-10-25 16:02:00 +02:00
}
bool has_locked_children(struct mount *mnt, struct dentry *dentry);
2024-12-13 00:03:44 +01:00
struct mnt_namespace *get_sequential_mnt_ns(struct mnt_namespace *mnt_ns,
bool previous);
2024-07-19 13:41:52 +02:00
static inline struct mnt_namespace *to_mnt_ns(struct ns_common *ns)
{
return container_of(ns, struct mnt_namespace, ns);
}
2025-01-29 17:58:00 +01:00
#ifdef CONFIG_FSNOTIFY
static inline void mnt_notify_add(struct mount *m)
{
/* Optimize the case where there are no watches */
if ((m->mnt_ns && m->mnt_ns->n_fsnotify_marks) ||
(m->prev_ns && m->prev_ns->n_fsnotify_marks))
list_add_tail(&m->to_notify, &notify_list);
else
m->prev_ns = m->mnt_ns;
}
#else
static inline void mnt_notify_add(struct mount *m)
{
}
#endif
2025-08-20 03:23:12 -04:00
static inline struct mount *topmost_overmount(struct mount *m)
{
while (m->overmount)
m = m->overmount;
return m;
}
2025-08-27 13:37:12 -04:00
static inline bool __test_write_hold(struct mount * __aligned(1) *val)
{
return (unsigned long)val & WRITE_HOLD;
}
static inline bool test_write_hold(const struct mount *m)
{
return __test_write_hold(m->mnt_pprev_for_sb);
}
static inline void set_write_hold(struct mount *m)
{
m->mnt_pprev_for_sb = (void *)((unsigned long)m->mnt_pprev_for_sb
| WRITE_HOLD);
}
static inline void clear_write_hold(struct mount *m)
{
m->mnt_pprev_for_sb = (void *)((unsigned long)m->mnt_pprev_for_sb
& ~WRITE_HOLD);
}
2025-01-29 17:58:00 +01:00
struct mnt_namespace *mnt_ns_from_dentry(struct dentry *dentry);