diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2025-06-21 18:06:19 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2025-06-29 19:03:29 -0400 |
| commit | 406fea79992561f47fd3511dd8b7c8abeeff7045 (patch) | |
| tree | 077af00d0d9850fcfdf1fe0e4a96ebf65c42eed8 /fs/pnode.c | |
| parent | 493a4bebf5157a5da64e36f8d468ff80a859b563 (diff) | |
| download | tip-406fea79992561f47fd3511dd8b7c8abeeff7045.tar.gz | |
mount: separate the flags accessed only under namespace_sem
Several flags are updated and checked only under namespace_sem; we are
already making use of that when we are checking them without mount_lock,
but we have to hold mount_lock for all updates, which makes things
clumsier than they have to be.
Take MNT_SHARED, MNT_UNBINDABLE, MNT_MARKED and MNT_UMOUNT_CANDIDATE
into a separate field (->mnt_t_flags), renaming them to T_SHARED,
etc. to avoid confusion. All accesses must be under namespace_sem.
That changes locking requirements for mnt_change_propagation() and
set_mnt_shared() - only namespace_sem is needed now. The same goes
for SET_MNT_MARKED et.al.
There might be more flags moved from ->mnt_flags to that field;
this is just the initial set.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/pnode.c')
| -rw-r--r-- | fs/pnode.c | 22 |
1 files changed, 10 insertions, 12 deletions
diff --git a/fs/pnode.c b/fs/pnode.c index 827d71736ac5bd..b997663de6d0b9 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -112,7 +112,7 @@ static int do_make_slave(struct mount *mnt) } /* - * vfsmount lock must be held for write + * EXCL[namespace_sem] */ void change_mnt_propagation(struct mount *mnt, int type) { @@ -125,9 +125,9 @@ void change_mnt_propagation(struct mount *mnt, int type) list_del_init(&mnt->mnt_slave); mnt->mnt_master = NULL; if (type == MS_UNBINDABLE) - mnt->mnt.mnt_flags |= MNT_UNBINDABLE; + mnt->mnt_t_flags |= T_UNBINDABLE; else - mnt->mnt.mnt_flags &= ~MNT_UNBINDABLE; + mnt->mnt_t_flags &= ~T_UNBINDABLE; } } @@ -263,9 +263,9 @@ static int propagate_one(struct mount *m, struct mountpoint *dest_mp) return PTR_ERR(child); read_seqlock_excl(&mount_lock); mnt_set_mountpoint(m, dest_mp, child); + read_sequnlock_excl(&mount_lock); if (m->mnt_master != dest_master) SET_MNT_MARK(m->mnt_master); - read_sequnlock_excl(&mount_lock); last_dest = m; last_source = child; hlist_add_head(&child->mnt_hash, list); @@ -322,13 +322,11 @@ int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp, } while (n != m); } out: - read_seqlock_excl(&mount_lock); hlist_for_each_entry(n, tree_list, mnt_hash) { m = n->mnt_parent; if (m->mnt_master != dest_mnt->mnt_master) CLEAR_MNT_MARK(m->mnt_master); } - read_sequnlock_excl(&mount_lock); return ret; } @@ -447,7 +445,7 @@ void propagate_mount_unlock(struct mount *mnt) static inline bool is_candidate(struct mount *m) { - return m->mnt.mnt_flags & MNT_UMOUNT_CANDIDATE; + return m->mnt_t_flags & T_UMOUNT_CANDIDATE; } static inline bool will_be_unmounted(struct mount *m) @@ -464,7 +462,7 @@ static void umount_one(struct mount *m, struct list_head *to_umount) static void remove_from_candidate_list(struct mount *m) { - m->mnt.mnt_flags &= ~(MNT_MARKED | MNT_UMOUNT_CANDIDATE); + m->mnt_t_flags &= ~(T_MARKED | T_UMOUNT_CANDIDATE); list_del_init(&m->mnt_list); } @@ -476,7 +474,7 @@ static void gather_candidates(struct list_head *set, list_for_each_entry(m, set, mnt_list) { if (is_candidate(m)) continue; - m->mnt.mnt_flags |= MNT_UMOUNT_CANDIDATE; + m->mnt_t_flags |= T_UMOUNT_CANDIDATE; p = m->mnt_parent; q = propagation_next(p, p); while (q) { @@ -494,7 +492,7 @@ static void gather_candidates(struct list_head *set, q = skip_propagation_subtree(q, p); continue; } - child->mnt.mnt_flags |= MNT_UMOUNT_CANDIDATE; + child->mnt_t_flags |= T_UMOUNT_CANDIDATE; if (!will_be_unmounted(child)) list_add(&child->mnt_list, candidates); } @@ -502,7 +500,7 @@ static void gather_candidates(struct list_head *set, } } list_for_each_entry(m, set, mnt_list) - m->mnt.mnt_flags &= ~MNT_UMOUNT_CANDIDATE; + m->mnt_t_flags &= ~T_UMOUNT_CANDIDATE; } /* @@ -519,7 +517,7 @@ static void trim_ancestors(struct mount *m) return; SET_MNT_MARK(m); if (m != p->overmount) - p->mnt.mnt_flags &= ~MNT_UMOUNT_CANDIDATE; + p->mnt_t_flags &= ~T_UMOUNT_CANDIDATE; } } |
