| 1 |
|
| 2 | #include <linux/mount.h>
|
| 3 | #include <linux/seq_file.h>
|
| 4 | #include <linux/poll.h>
|
| 5 | #include <linux/ns_common.h>
|
| 6 | #include <linux/fs_pin.h>
|
| 7 |
|
| 8 | extern struct file_system_type nullfs_fs_type;
|
| 9 | extern struct dentry *nullfs_new_file(struct super_block *sb);
|
| 10 | extern struct vfsmount *knullfs;
|
| 11 | extern struct list_head notify_list;
|
| 12 |
|
| 13 | struct mnt_namespace {
|
| 14 | struct ns_common ns;
|
| 15 | struct mount * root;
|
| 16 | struct {
|
| 17 | struct rb_root mounts;
|
| 18 | struct rb_node *mnt_last_node;
|
| 19 | struct rb_node *mnt_first_node;
|
| 20 | };
|
| 21 | struct user_namespace *user_ns;
|
| 22 | struct ucounts *ucounts;
|
| 23 | wait_queue_head_t poll;
|
| 24 | u64 seq_origin;
|
| 25 | u64 event;
|
| 26 | #ifdef CONFIG_FSNOTIFY
|
| 27 | __u32 n_fsnotify_mask;
|
| 28 | struct fsnotify_mark_connector __rcu *n_fsnotify_marks;
|
| 29 | #endif
|
| 30 | struct hlist_head mnt_visible_mounts;
|
| 31 | unsigned int nr_mounts;
|
| 32 | unsigned int pending_mounts;
|
| 33 | refcount_t passive;
|
| 34 | bool is_anon;
|
| 35 | } __randomize_layout;
|
| 36 |
|
| 37 | struct mnt_pcp {
|
| 38 | unsigned int mnt_gets;
|
| 39 | unsigned int mnt_puts;
|
| 40 | int mnt_writers;
|
| 41 | };
|
| 42 |
|
| 43 | struct mountpoint {
|
| 44 | struct hlist_node m_hash;
|
| 45 | struct dentry *m_dentry;
|
| 46 | struct hlist_head m_list;
|
| 47 | struct hlist_head m_covers;
|
| 48 | };
|
| 49 |
|
| 50 | struct mnt_cover;
|
| 51 |
|
| 52 | struct mount {
|
| 53 | struct hlist_node mnt_hash;
|
| 54 | struct mount *mnt_parent;
|
| 55 | struct dentry *mnt_mountpoint;
|
| 56 | struct vfsmount mnt;
|
| 57 | union {
|
| 58 | struct rb_node mnt_node;
|
| 59 | struct rcu_head mnt_rcu;
|
| 60 | struct llist_node mnt_llist;
|
| 61 | };
|
| 62 | #ifdef CONFIG_SMP
|
| 63 | struct mnt_pcp __percpu *mnt_pcp;
|
| 64 | #else
|
| 65 | int mnt_count;
|
| 66 | int mnt_writers;
|
| 67 | #endif
|
| 68 | struct list_head mnt_mounts;
|
| 69 | struct list_head mnt_child;
|
| 70 | struct mount *mnt_next_for_sb;
|
| 71 | struct mount * __aligned(1) *mnt_pprev_for_sb;
|
| 72 |
|
| 73 | #define WRITE_HOLD 1
|
| 74 | const char *mnt_devname;
|
| 75 | struct list_head mnt_list;
|
| 76 | struct list_head mnt_expire;
|
| 77 | struct list_head mnt_share;
|
| 78 | struct hlist_head mnt_slave_list;
|
| 79 | struct hlist_node mnt_slave;
|
| 80 | struct mount *mnt_master;
|
| 81 | |
| 82 | * Containing namespace (active or deactivating, non-refcounted).
|
| 83 | * Normally protected by namespace_sem.
|
| 84 | * Can also be accessed locklessly under RCU. RCU readers can't rely on
|
| 85 | * the namespace still being active, but implicitly hold a passive
|
| 86 | * reference (because an RCU delay happens between a namespace being
|
| 87 | * deactivated and the corresponding passive refcount drop).
|
| 88 |
|
| 89 | struct mnt_namespace *mnt_ns;
|
| 90 | struct mountpoint *mnt_mp;
|
| 91 | union {
|
| 92 | struct hlist_node mnt_mp_list;
|
| 93 | struct hlist_node mnt_umount;
|
| 94 | };
|
| 95 | #ifdef CONFIG_FSNOTIFY
|
| 96 | struct fsnotify_mark_connector __rcu *mnt_fsnotify_marks;
|
| 97 | __u32 mnt_fsnotify_mask;
|
| 98 | struct list_head to_notify;
|
| 99 | struct mnt_namespace *prev_ns;
|
| 100 | #endif
|
| 101 | int mnt_t_flags;
|
| 102 | int mnt_id;
|
| 103 | u64 mnt_id_unique;
|
| 104 | int mnt_group_id;
|
| 105 | int mnt_expiry_mark;
|
| 106 | struct hlist_head mnt_pins;
|
| 107 | struct mnt_cover *mnt_cover;
|
| 108 | struct hlist_head mnt_covers;
|
| 109 | struct hlist_node mnt_ns_visible;
|
| 110 | struct mount *overmount;
|
| 111 | } __randomize_layout;
|
| 112 |
|
| 113 | enum {
|
| 114 | T_SHARED = 1,
|
| 115 | T_UNBINDABLE = 2,
|
| 116 | T_MARKED = 4,
|
| 117 | T_UMOUNT_CANDIDATE = 8,
|
| 118 |
|
| 119 | |
| 120 | * T_SHARED_MASK is the set of flags that should be cleared when a
|
| 121 | * mount becomes shared. Currently, this is only the flag that says a
|
| 122 | * mount cannot be bind mounted, since this is how we create a mount
|
| 123 | * that shares events with another mount. If you add a new T_*
|
| 124 | * flag, consider how it interacts with shared mounts.
|
| 125 |
|
| 126 | T_SHARED_MASK = T_UNBINDABLE,
|
| 127 | };
|
| 128 |
|
| 129 | #define MNT_NS_INTERNAL ERR_PTR(-EINVAL)
|
| 130 |
|
| 131 | static inline struct mount *real_mount(struct vfsmount *mnt)
|
| 132 | {
|
| 133 | return container_of(mnt, struct mount, mnt);
|
| 134 | }
|
| 135 |
|
| 136 | static inline int mnt_has_parent(const struct mount *mnt)
|
| 137 | {
|
| 138 | return mnt != mnt->mnt_parent;
|
| 139 | }
|
| 140 |
|
| 141 | static inline int is_mounted(struct vfsmount *mnt)
|
| 142 | {
|
| 143 |
|
| 144 | return !IS_ERR_OR_NULL(real_mount(mnt)->mnt_ns);
|
| 145 | }
|
| 146 |
|
| 147 | extern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *);
|
| 148 |
|
| 149 | extern int __legitimize_mnt(struct vfsmount *, unsigned);
|
| 150 |
|
| 151 | static inline bool __path_is_mountpoint(const struct path *path)
|
| 152 | {
|
| 153 | struct mount *m = __lookup_mnt(path->mnt, path->dentry);
|
| 154 | return m && likely(!(m->mnt.mnt_flags & MNT_SYNC_UMOUNT));
|
| 155 | }
|
| 156 |
|
| 157 | extern void __detach_mounts(struct dentry *dentry);
|
| 158 |
|
| 159 | static inline void detach_mounts(struct dentry *dentry)
|
| 160 | {
|
| 161 | if (!d_mountpoint(dentry))
|
| 162 | return;
|
| 163 | __detach_mounts(dentry);
|
| 164 | }
|
| 165 |
|
| 166 | static inline void get_mnt_ns(struct mnt_namespace *ns)
|
| 167 | {
|
| 168 | ns_ref_inc(ns);
|
| 169 | }
|
| 170 |
|
| 171 | extern seqlock_t mount_lock;
|
| 172 |
|
| 173 | DEFINE_LOCK_GUARD_0(mount_writer, write_seqlock(&mount_lock),
|
| 174 | write_sequnlock(&mount_lock))
|
| 175 | DEFINE_LOCK_GUARD_0(mount_locked_reader, read_seqlock_excl(&mount_lock),
|
| 176 | read_sequnlock_excl(&mount_lock))
|
| 177 |
|
| 178 | struct proc_mounts {
|
| 179 | struct mnt_namespace *ns;
|
| 180 | struct path root;
|
| 181 | int (*show)(struct seq_file *, struct vfsmount *);
|
| 182 | };
|
| 183 |
|
| 184 | extern const struct seq_operations mounts_op;
|
| 185 |
|
| 186 | extern bool __is_local_mountpoint(const struct dentry *dentry);
|
| 187 | static inline bool is_local_mountpoint(const struct dentry *dentry)
|
| 188 | {
|
| 189 | if (!d_mountpoint(dentry))
|
| 190 | return false;
|
| 191 |
|
| 192 | return __is_local_mountpoint(dentry);
|
| 193 | }
|
| 194 |
|
| 195 | static inline bool is_anon_ns(struct mnt_namespace *ns)
|
| 196 | {
|
| 197 | return ns->is_anon;
|
| 198 | }
|
| 199 |
|
| 200 | static inline bool anon_ns_root(const struct mount *m)
|
| 201 | {
|
| 202 | struct mnt_namespace *ns = READ_ONCE(m->mnt_ns);
|
| 203 |
|
| 204 | return !IS_ERR_OR_NULL(ns) && is_anon_ns(ns) && m == ns->root;
|
| 205 | }
|
| 206 |
|
| 207 | static inline bool mnt_ns_attached(const struct mount *mnt)
|
| 208 | {
|
| 209 | return !RB_EMPTY_NODE(&mnt->mnt_node);
|
| 210 | }
|
| 211 |
|
| 212 | static inline bool mnt_ns_empty(const struct mnt_namespace *ns)
|
| 213 | {
|
| 214 | return RB_EMPTY_ROOT(&ns->mounts);
|
| 215 | }
|
| 216 |
|
| 217 | static inline void move_from_ns(struct mount *mnt)
|
| 218 | {
|
| 219 | struct mnt_namespace *ns = mnt->mnt_ns;
|
| 220 | WARN_ON(!mnt_ns_attached(mnt));
|
| 221 | if (ns->mnt_last_node == &mnt->mnt_node)
|
| 222 | ns->mnt_last_node = rb_prev(&mnt->mnt_node);
|
| 223 | if (ns->mnt_first_node == &mnt->mnt_node)
|
| 224 | ns->mnt_first_node = rb_next(&mnt->mnt_node);
|
| 225 | rb_erase(&mnt->mnt_node, &ns->mounts);
|
| 226 | RB_CLEAR_NODE(&mnt->mnt_node);
|
| 227 | if (!hlist_unhashed(&mnt->mnt_ns_visible))
|
| 228 | hlist_del_init(&mnt->mnt_ns_visible);
|
| 229 | }
|
| 230 |
|
| 231 | bool has_locked_children(struct mount *mnt, struct dentry *dentry);
|
| 232 | struct mnt_namespace *get_sequential_mnt_ns(struct mnt_namespace *mnt_ns,
|
| 233 | bool previous);
|
| 234 |
|
| 235 | static inline struct mnt_namespace *to_mnt_ns(struct ns_common *ns)
|
| 236 | {
|
| 237 | return container_of(ns, struct mnt_namespace, ns);
|
| 238 | }
|
| 239 |
|
| 240 | #ifdef CONFIG_FSNOTIFY
|
| 241 | static inline void mnt_notify_add(struct mount *m)
|
| 242 | {
|
| 243 |
|
| 244 | if (!list_empty(&m->to_notify))
|
| 245 | return;
|
| 246 |
|
| 247 | if ((m->mnt_ns && m->mnt_ns->n_fsnotify_marks) ||
|
| 248 | (m->prev_ns && m->prev_ns->n_fsnotify_marks))
|
| 249 | list_add_tail(&m->to_notify, ¬ify_list);
|
| 250 | else
|
| 251 | m->prev_ns = m->mnt_ns;
|
| 252 | }
|
| 253 | #else
|
| 254 | static inline void mnt_notify_add(struct mount *m)
|
| 255 | {
|
| 256 | }
|
| 257 | #endif
|
| 258 |
|
| 259 | static inline struct mount *topmost_overmount(struct mount *m)
|
| 260 | {
|
| 261 | while (m->overmount)
|
| 262 | m = m->overmount;
|
| 263 | return m;
|
| 264 | }
|
| 265 |
|
| 266 | static inline bool __test_write_hold(struct mount * __aligned(1) *val)
|
| 267 | {
|
| 268 | return (unsigned long)val & WRITE_HOLD;
|
| 269 | }
|
| 270 |
|
| 271 | static inline bool test_write_hold(const struct mount *m)
|
| 272 | {
|
| 273 | return __test_write_hold(m->mnt_pprev_for_sb);
|
| 274 | }
|
| 275 |
|
| 276 | static inline void set_write_hold(struct mount *m)
|
| 277 | {
|
| 278 | m->mnt_pprev_for_sb = (void *)((unsigned long)m->mnt_pprev_for_sb
|
| 279 | | WRITE_HOLD);
|
| 280 | }
|
| 281 |
|
| 282 | static inline void clear_write_hold(struct mount *m)
|
| 283 | {
|
| 284 | m->mnt_pprev_for_sb = (void *)((unsigned long)m->mnt_pprev_for_sb
|
| 285 | & ~WRITE_HOLD);
|
| 286 | }
|
| 287 |
|
| 288 | struct mnt_namespace *mnt_ns_from_dentry(struct dentry *dentry);
|