diff options
| author | Christian Brauner <brauner@kernel.org> | 2026-10-11 17:30:44 +0200 |
|---|---|---|
| committer | Christian Brauner <brauner@kernel.org> | 2026-10-12 12:22:14 +0200 |
| commit | 0773e3ceb2a822c142dfcb9ff83c2cde9ee8e225 (patch) | |
| tree | d429fb52d6af0cd1f9e6e33f0ef64f06830c4d57 /tools/lib/python | |
| parent | 23194f382636f51511a3ceb4b579ad586643c8ac (diff) | |
| download | linux-next-0773e3ceb2a822c142dfcb9ff83c2cde9ee8e225.tar.gz linux-next-0773e3ceb2a822c142dfcb9ff83c2cde9ee8e225.zip | |
fs: drop the smp_mb()s that mnt_get_count() made redundant
Both mntput_no_expire_slowpath() and do_umount() have an smp_mb()
between taking mount_lock and summing up the reference count. They pair
with the smp_mb() in __legitimize_mnt().
A walker in __legitimize_mnt() increments the count and then re-reads
the seqcount of mount_lock. The unmounter writes the seqcount when it
takes mount_lock and then sums up the count. They must not both miss
each other's store. Otherwise the walker keeps a reference to a mount
that the unmounter finishes off. That's the store buffering pattern and
it needs a full barrier between the store and the load on both sides.
In commit 119e1ef80ecf ("fix __legitimize_mnt()/mntput() race") the
barrier in the slow path of mntput_no_expire() as added and the one in
do_umount() in commit 65781e19dcfc ("do_umount(): add missing barrier
before refcount checks in sync case"). Back then mnt_get_count() didn't
have a barrier of its own.
Since commit 7eb84d54fac5 ("fs: don't let a migrating task hide its
reference from do_umount()") it does. It sums up the puts, does an
smp_mb() and then sums up the gets. In program order that barrier sits
after the seqcount write in lock_mount_hash() and before the loads of
the gets. That's all the walker needs. If the sum misses the walker's
increment the walker sees the seqcount change and drops its reference
under mount_lock where it finds MNT_DOOMED or MNT_SYNC_UMOUNT.
The only thing the outer barrier orders on top of that is the seqcount
write against the loads of the puts and nothing relies on it:
(1) A put from the fast path of mntput_no_expire() never looks at the
seqcount. If the sum misses such a put that's what the grace period
is for.
(2) All other puts happen under mount_lock and are ordered by it.
(3) The slow path's own decrement right before the sum is a store on the
same cpu and is read back in program order.
So the outer barriers don't order anything that the inner one doesn't.
That argument is made in the kernel memory model and every architecture
has to implement its barriers according to it. herd7 against
tools/memory-model agrees. Without the outer smp_mb() the walker against
the slow path and against the busy check in do_umount() is "Never". If
the inner smp_mb() goes as well it's "Sometimes". The litmus tests for
this are in the next patch.
Make the comments in __legitimize_mnt() and mnt_get_count() point at
each other.
Link: https://patch.msgid.link/20261011-work-mount-fixes-5-v1-1-a9b9a8ecf565@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Diffstat (limited to 'tools/lib/python')
0 files changed, 0 insertions, 0 deletions
