Skip to content

Commit a68cb18

Browse files
committed
mount: add a comment about concurrent changes with statmount()/listmount()
Add some comments in there highlighting a few non-obvious assumptions. Link: https://lore.kernel.org/20250416-zerknirschen-aluminium-14a55639076f@brauner Signed-off-by: Christian Brauner <[email protected]>
1 parent 0af2f6b commit a68cb18

File tree

1 file changed

+23
-3
lines changed

1 file changed

+23
-3
lines changed

fs/namespace.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5831,13 +5831,29 @@ static int do_statmount(struct kstatmount *s, u64 mnt_id, u64 mnt_ns_id,
58315831
return err;
58325832

58335833
s->root = root;
5834-
s->idmap = mnt_idmap(s->mnt);
5835-
if (s->mask & STATMOUNT_SB_BASIC)
5836-
statmount_sb_basic(s);
58375834

5835+
/*
5836+
* Note that mount properties in mnt->mnt_flags, mnt->mnt_idmap
5837+
* can change concurrently as we only hold the read-side of the
5838+
* namespace semaphore and mount properties may change with only
5839+
* the mount lock held.
5840+
*
5841+
* We could sample the mount lock sequence counter to detect
5842+
* those changes and retry. But it's not worth it. Worst that
5843+
* happens is that the mnt->mnt_idmap pointer is already changed
5844+
* while mnt->mnt_flags isn't or vica versa. So what.
5845+
*
5846+
* Both mnt->mnt_flags and mnt->mnt_idmap are set and retrieved
5847+
* via READ_ONCE()/WRITE_ONCE() and guard against theoretical
5848+
* torn read/write. That's all we care about right now.
5849+
*/
5850+
s->idmap = mnt_idmap(s->mnt);
58385851
if (s->mask & STATMOUNT_MNT_BASIC)
58395852
statmount_mnt_basic(s);
58405853

5854+
if (s->mask & STATMOUNT_SB_BASIC)
5855+
statmount_sb_basic(s);
5856+
58415857
if (s->mask & STATMOUNT_PROPAGATE_FROM)
58425858
statmount_propagate_from(s);
58435859

@@ -6149,6 +6165,10 @@ SYSCALL_DEFINE4(listmount, const struct mnt_id_req __user *, req,
61496165
!ns_capable_noaudit(ns->user_ns, CAP_SYS_ADMIN))
61506166
return -ENOENT;
61516167

6168+
/*
6169+
* We only need to guard against mount topology changes as
6170+
* listmount() doesn't care about any mount properties.
6171+
*/
61526172
scoped_guard(rwsem_read, &namespace_sem)
61536173
ret = do_listmount(ns, kreq.mnt_id, last_mnt_id, kmnt_ids,
61546174
nr_mnt_ids, (flags & LISTMOUNT_REVERSE));

0 commit comments

Comments
 (0)