From: Al Viro Date: Sat, 21 Jun 2025 21:41:40 +0000 (-0400) Subject: propagate_one(): get rid of dest_master X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=25776a09d802f4e4d8c0bd72042934223286c2e3;p=thirdparty%2Fkernel%2Flinux.git propagate_one(): get rid of dest_master propagate_mnt() takes the subtree we are about to attach and creates its copies, setting the propagation between those. Each copy is cloned either from the original or from one of the already created copies. The tricky part is choosing the right copy to serve as a master when we are starting a new peer group. The algorithm for doing that selection puts temporary marks on the masters of mountpoints that already got a copy created for them; since the initial peer group might have no master at all, we need to special-case that when looking for the mark. Currently we do that by memorizing the master of original peer group. It works, but we get yet another piece of data to pass from propagate_mnt() to propagate_one(). Alternative is to mark the master of original peer group if not NULL, turning the check into "master is NULL or marked". Less data to pass around and memory safety is more obvious that way... Signed-off-by: Al Viro --- diff --git a/fs/pnode.c b/fs/pnode.c index b997663de6d0b..870ebced10aa7 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -215,7 +215,7 @@ static struct mount *next_group(struct mount *m, struct mount *origin) } /* all accesses are serialized by namespace_sem */ -static struct mount *last_dest, *first_source, *last_source, *dest_master; +static struct mount *last_dest, *first_source, *last_source; static struct hlist_head *list; static int propagate_one(struct mount *m, struct mountpoint *dest_mp) @@ -239,7 +239,7 @@ static int propagate_one(struct mount *m, struct mountpoint *dest_mp) bool done; for (n = m; ; n = p) { p = n->mnt_master; - if (p == dest_master || IS_MNT_MARKED(p)) + if (!p || IS_MNT_MARKED(p)) break; } do { @@ -264,7 +264,7 @@ static int propagate_one(struct mount *m, struct mountpoint *dest_mp) read_seqlock_excl(&mount_lock); mnt_set_mountpoint(m, dest_mp, child); read_sequnlock_excl(&mount_lock); - if (m->mnt_master != dest_master) + if (m->mnt_master) SET_MNT_MARK(m->mnt_master); last_dest = m; last_source = child; @@ -300,7 +300,8 @@ int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp, first_source = source_mnt; last_source = source_mnt; list = tree_list; - dest_master = dest_mnt->mnt_master; + if (dest_mnt->mnt_master) + SET_MNT_MARK(dest_mnt->mnt_master); /* all peers of dest_mnt, except dest_mnt itself */ for (n = next_peer(dest_mnt); n != dest_mnt; n = next_peer(n)) { @@ -324,9 +325,11 @@ int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp, out: hlist_for_each_entry(n, tree_list, mnt_hash) { m = n->mnt_parent; - if (m->mnt_master != dest_mnt->mnt_master) + if (m->mnt_master) CLEAR_MNT_MARK(m->mnt_master); } + if (dest_mnt->mnt_master) + CLEAR_MNT_MARK(dest_mnt->mnt_master); return ret; }