fix propagation graph breakage by MOVE_MOUNT_SET_GROUP move_mount(2)
[ Upstream commit d8cc0362f918d020ca1340d7694f07062dc30f36 ]9ffb14ef61
"move_mount: allow to add a mount into an existing group" breaks assertions on ->mnt_share/->mnt_slave. For once, the data structures in question are actually documented. Documentation/filesystem/sharedsubtree.rst: All vfsmounts in a peer group have the same ->mnt_master. If it is non-NULL, they form a contiguous (ordered) segment of slave list. do_set_group() puts a mount into the same place in propagation graph as the old one. As the result, if old mount gets events from somewhere and is not a pure event sink, new one needs to be placed next to the old one in the slave list the old one's on. If it is a pure event sink, we only need to make sure the new one doesn't end up in the middle of some peer group. "move_mount: allow to add a mount into an existing group" ends up putting the new one in the beginning of list; that's definitely not going to be in the middle of anything, so that's fine for case when old is not marked shared. In case when old one _is_ marked shared (i.e. is not a pure event sink), that breaks the assumptions of propagation graph iterators. Put the new mount next to the old one on the list - that does the right thing in "old is marked shared" case and is just as correct as the current behaviour if old is not marked shared (kudos to Pavel for pointing that out - my original suggested fix changed behaviour in the "nor marked" case, which complicated things for no good reason). Reviewed-by: Christian Brauner <brauner@kernel.org> Fixes:9ffb14ef61
("move_mount: allow to add a mount into an existing group") Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Sasha Levin <sashal@kernel.org> (cherry picked from commit 3d1ea8e048acc2a482154c89487f5e803ac189f8)
This commit is contained in:
parent
d013bbf074
commit
1ee6ad481b
|
@ -2995,7 +2995,7 @@ static int do_set_group(struct path *from_path, struct path *to_path)
|
|||
if (IS_MNT_SLAVE(from)) {
|
||||
struct mount *m = from->mnt_master;
|
||||
|
||||
list_add(&to->mnt_slave, &m->mnt_slave_list);
|
||||
list_add(&to->mnt_slave, &from->mnt_slave);
|
||||
to->mnt_master = m;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue