Skip to content

Commit 794cbac

Browse files
committed
Merge tag 'pull-mount' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs mount updates from Al Viro: - mount hash conflicts rudiments are gone now - we do not allow multiple mounts with the same parent/mountpoint to be hashed at the same time. - 'struct mount' changes: - mnt_umounting is gone - mnt_slave_list/mnt_slave is an hlist now - overmounts are kept track of by explicit pointer in mount - a bunch of flags moved out of mnt_flags to a new field, with only namespace_sem for protection - mnt_expiry is protected by mount_lock now (instead of namespace_sem) - MNT_LOCKED is used only for mounts that need to remain attached to their parents to prevent mountpoint exposure - no more overloading it for absolute roots - all mnt_list uses are transient now - it's used only to represent temporary sets during umount_tree() - mount refcounting change: children no longer pin parents for any mounts, whether they'd passed through umount_tree() or not - 'struct mountpoint' changes: - refcount is no more; what matters is ->m_list emptiness - instead of temporary bumping the refcount, we insert a new object (pinned_mountpoint) into ->m_list - new calling conventions for lock_mount() and friends - do_move_mount()/attach_recursive_mnt() seriously cleaned up - globals in fs/pnode.c are gone - propagate_mnt(), change_mnt_propagation() and propagate_umount() cleaned up (in the last case - pretty much completely rewritten). - freeing of emptied mnt_namespace is done in namespace_unlock(). For one thing, there are subtle ordering requirements there; for another it simplifies cleanups. - assorted cleanups - restore the machinery for long-term mounts from accumulated bitrot. This is going to get a followup come next cycle, when the change of vfs_fs_parse_string() calling conventions goes into -next * tag 'pull-mount' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (48 commits) statmount_mnt_basic(): simplify the logics for group id invent_group_ids(): zero ->mnt_group_id always implies !IS_MNT_SHARED() get rid of CL_SHARE_TO_SLAVE take freeing of emptied mnt_namespace to namespace_unlock() copy_tree(): don't link the mounts via mnt_list change_mnt_propagation(): move ->mnt_master assignment into MS_SLAVE case mnt_slave_list/mnt_slave: turn into hlist_head/hlist_node turn do_make_slave() into transfer_propagation() do_make_slave(): choose new master sanely change_mnt_propagation(): do_make_slave() is a no-op unless IS_MNT_SHARED() change_mnt_propagation() cleanups, step 1 propagate_mnt(): fix comment and convert to kernel-doc, while we are at it propagate_mnt(): get rid of last_dest fs/pnode.c: get rid of globals propagate_one(): fold into the sole caller propagate_one(): separate the "what should be the master for this copy" part propagate_one(): separate the "do we need secondary here?" logics propagate_mnt(): handle all peer groups in the same loop propagate_one(): get rid of dest_master mount: separate the flags accessed only under namespace_sem ...
2 parents 953e117 + a7cce09 commit 794cbac

File tree

10 files changed

+1216
-807
lines changed

10 files changed

+1216
-807
lines changed

Documentation/filesystems/propagate_umount.txt

Lines changed: 484 additions & 0 deletions
Large diffs are not rendered by default.

drivers/gpu/drm/i915/gem/i915_gemfs.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,23 @@
55

66
#include <linux/fs.h>
77
#include <linux/mount.h>
8+
#include <linux/fs_context.h>
89

910
#include "i915_drv.h"
1011
#include "i915_gemfs.h"
1112
#include "i915_utils.h"
1213

14+
static int add_param(struct fs_context *fc, const char *key, const char *val)
15+
{
16+
return vfs_parse_fs_string(fc, key, val, strlen(val));
17+
}
18+
1319
void i915_gemfs_init(struct drm_i915_private *i915)
1420
{
15-
char huge_opt[] = "huge=within_size"; /* r/w */
1621
struct file_system_type *type;
22+
struct fs_context *fc;
1723
struct vfsmount *gemfs;
24+
int ret;
1825

1926
/*
2027
* By creating our own shmemfs mountpoint, we can pass in
@@ -38,8 +45,16 @@ void i915_gemfs_init(struct drm_i915_private *i915)
3845
if (!type)
3946
goto err;
4047

41-
gemfs = vfs_kern_mount(type, SB_KERNMOUNT, type->name, huge_opt);
42-
if (IS_ERR(gemfs))
48+
fc = fs_context_for_mount(type, SB_KERNMOUNT);
49+
if (IS_ERR(fc))
50+
goto err;
51+
ret = add_param(fc, "source", "tmpfs");
52+
if (!ret)
53+
ret = add_param(fc, "huge", "within_size");
54+
if (!ret)
55+
gemfs = fc_mount_longterm(fc);
56+
put_fs_context(fc);
57+
if (ret)
4358
goto err;
4459

4560
i915->mm.gemfs = gemfs;

drivers/gpu/drm/v3d/v3d_gemfs.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,21 @@
33

44
#include <linux/fs.h>
55
#include <linux/mount.h>
6+
#include <linux/fs_context.h>
67

78
#include "v3d_drv.h"
89

10+
static int add_param(struct fs_context *fc, const char *key, const char *val)
11+
{
12+
return vfs_parse_fs_string(fc, key, val, strlen(val));
13+
}
14+
915
void v3d_gemfs_init(struct v3d_dev *v3d)
1016
{
11-
char huge_opt[] = "huge=within_size";
1217
struct file_system_type *type;
18+
struct fs_context *fc;
1319
struct vfsmount *gemfs;
20+
int ret;
1421

1522
/*
1623
* By creating our own shmemfs mountpoint, we can pass in
@@ -28,8 +35,16 @@ void v3d_gemfs_init(struct v3d_dev *v3d)
2835
if (!type)
2936
goto err;
3037

31-
gemfs = vfs_kern_mount(type, SB_KERNMOUNT, type->name, huge_opt);
32-
if (IS_ERR(gemfs))
38+
fc = fs_context_for_mount(type, SB_KERNMOUNT);
39+
if (IS_ERR(fc))
40+
goto err;
41+
ret = add_param(fc, "source", "tmpfs");
42+
if (!ret)
43+
ret = add_param(fc, "huge", "within_size");
44+
if (!ret)
45+
gemfs = fc_mount_longterm(fc);
46+
put_fs_context(fc);
47+
if (ret)
3348
goto err;
3449

3550
v3d->gemfs = gemfs;

fs/hugetlbfs/inode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1588,7 +1588,7 @@ static struct vfsmount *__init mount_one_hugetlbfs(struct hstate *h)
15881588
} else {
15891589
struct hugetlbfs_fs_context *ctx = fc->fs_private;
15901590
ctx->hstate = h;
1591-
mnt = fc_mount(fc);
1591+
mnt = fc_mount_longterm(fc);
15921592
put_fs_context(fc);
15931593
}
15941594
if (IS_ERR(mnt))

fs/mount.h

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ struct mountpoint {
4444
struct hlist_node m_hash;
4545
struct dentry *m_dentry;
4646
struct hlist_head m_list;
47-
int m_count;
4847
};
4948

5049
struct mount {
@@ -70,38 +69,55 @@ struct mount {
7069
struct list_head mnt_list;
7170
struct list_head mnt_expire; /* link in fs-specific expiry list */
7271
struct list_head mnt_share; /* circular list of shared mounts */
73-
struct list_head mnt_slave_list;/* list of slave mounts */
74-
struct list_head mnt_slave; /* slave list entry */
72+
struct hlist_head mnt_slave_list;/* list of slave mounts */
73+
struct hlist_node mnt_slave; /* slave list entry */
7574
struct mount *mnt_master; /* slave is on master->mnt_slave_list */
7675
struct mnt_namespace *mnt_ns; /* containing namespace */
7776
struct mountpoint *mnt_mp; /* where is it mounted */
7877
union {
7978
struct hlist_node mnt_mp_list; /* list mounts with the same mountpoint */
8079
struct hlist_node mnt_umount;
8180
};
82-
struct list_head mnt_umounting; /* list entry for umount propagation */
8381
#ifdef CONFIG_FSNOTIFY
8482
struct fsnotify_mark_connector __rcu *mnt_fsnotify_marks;
8583
__u32 mnt_fsnotify_mask;
8684
struct list_head to_notify; /* need to queue notification */
8785
struct mnt_namespace *prev_ns; /* previous namespace (NULL if none) */
8886
#endif
87+
int mnt_t_flags; /* namespace_sem-protected flags */
8988
int mnt_id; /* mount identifier, reused */
9089
u64 mnt_id_unique; /* mount ID unique until reboot */
9190
int mnt_group_id; /* peer group identifier */
9291
int mnt_expiry_mark; /* true if marked for expiry */
9392
struct hlist_head mnt_pins;
9493
struct hlist_head mnt_stuck_children;
94+
struct mount *overmount; /* mounted on ->mnt_root */
9595
} __randomize_layout;
9696

97+
enum {
98+
T_SHARED = 1, /* mount is shared */
99+
T_UNBINDABLE = 2, /* mount is unbindable */
100+
T_MARKED = 4, /* internal mark for propagate_... */
101+
T_UMOUNT_CANDIDATE = 8, /* for propagate_umount */
102+
103+
/*
104+
* T_SHARED_MASK is the set of flags that should be cleared when a
105+
* mount becomes shared. Currently, this is only the flag that says a
106+
* mount cannot be bind mounted, since this is how we create a mount
107+
* that shares events with another mount. If you add a new T_*
108+
* flag, consider how it interacts with shared mounts.
109+
*/
110+
T_SHARED_MASK = T_UNBINDABLE,
111+
};
112+
97113
#define MNT_NS_INTERNAL ERR_PTR(-EINVAL) /* distinct from any mnt_namespace */
98114

99115
static inline struct mount *real_mount(struct vfsmount *mnt)
100116
{
101117
return container_of(mnt, struct mount, mnt);
102118
}
103119

104-
static inline int mnt_has_parent(struct mount *mnt)
120+
static inline int mnt_has_parent(const struct mount *mnt)
105121
{
106122
return mnt != mnt->mnt_parent;
107123
}
@@ -146,8 +162,8 @@ struct proc_mounts {
146162

147163
extern const struct seq_operations mounts_op;
148164

149-
extern bool __is_local_mountpoint(struct dentry *dentry);
150-
static inline bool is_local_mountpoint(struct dentry *dentry)
165+
extern bool __is_local_mountpoint(const struct dentry *dentry);
166+
static inline bool is_local_mountpoint(const struct dentry *dentry)
151167
{
152168
if (!d_mountpoint(dentry))
153169
return false;
@@ -160,6 +176,13 @@ static inline bool is_anon_ns(struct mnt_namespace *ns)
160176
return ns->seq == 0;
161177
}
162178

179+
static inline bool anon_ns_root(const struct mount *m)
180+
{
181+
struct mnt_namespace *ns = READ_ONCE(m->mnt_ns);
182+
183+
return !IS_ERR_OR_NULL(ns) && is_anon_ns(ns) && m == ns->root;
184+
}
185+
163186
static inline bool mnt_ns_attached(const struct mount *mnt)
164187
{
165188
return !RB_EMPTY_NODE(&mnt->mnt_node);
@@ -170,7 +193,7 @@ static inline bool mnt_ns_empty(const struct mnt_namespace *ns)
170193
return RB_EMPTY_ROOT(&ns->mounts);
171194
}
172195

173-
static inline void move_from_ns(struct mount *mnt, struct list_head *dt_list)
196+
static inline void move_from_ns(struct mount *mnt)
174197
{
175198
struct mnt_namespace *ns = mnt->mnt_ns;
176199
WARN_ON(!mnt_ns_attached(mnt));
@@ -180,7 +203,6 @@ static inline void move_from_ns(struct mount *mnt, struct list_head *dt_list)
180203
ns->mnt_first_node = rb_next(&mnt->mnt_node);
181204
rb_erase(&mnt->mnt_node, &ns->mounts);
182205
RB_CLEAR_NODE(&mnt->mnt_node);
183-
list_add_tail(&mnt->mnt_list, dt_list);
184206
}
185207

186208
bool has_locked_children(struct mount *mnt, struct dentry *dentry);

0 commit comments

Comments
 (0)