Skip to content

Commit bfef6e1

Browse files
mjguzikbrauner
authored andcommitted
fs: move mntput_no_expire() slowpath into a dedicated routine
In the stock variant the compiler spills several registers on the stack and employs stack smashing protection, adding even more code + a branch on exit.. The actual fast path is small enough that the compiler inlines it for all callers -- the symbol is no longer emitted. Forcing noinline on it just for code-measurement purposes shows the fast path dropping from 111 to 39 bytes. Signed-off-by: Mateusz Guzik <mjguzik@gmail.com> Link: https://patch.msgid.link/20251114201803.2183505-1-mjguzik@gmail.com Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent 6d228c1 commit bfef6e1

1 file changed

Lines changed: 22 additions & 16 deletions

File tree

fs/namespace.c

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,26 +1345,12 @@ static void delayed_mntput(struct work_struct *unused)
13451345
}
13461346
static DECLARE_DELAYED_WORK(delayed_mntput_work, delayed_mntput);
13471347

1348-
static void mntput_no_expire(struct mount *mnt)
1348+
static void noinline mntput_no_expire_slowpath(struct mount *mnt)
13491349
{
13501350
LIST_HEAD(list);
13511351
int count;
13521352

1353-
rcu_read_lock();
1354-
if (likely(READ_ONCE(mnt->mnt_ns))) {
1355-
/*
1356-
* Since we don't do lock_mount_hash() here,
1357-
* ->mnt_ns can change under us. However, if it's
1358-
* non-NULL, then there's a reference that won't
1359-
* be dropped until after an RCU delay done after
1360-
* turning ->mnt_ns NULL. So if we observe it
1361-
* non-NULL under rcu_read_lock(), the reference
1362-
* we are dropping is not the final one.
1363-
*/
1364-
mnt_add_count(mnt, -1);
1365-
rcu_read_unlock();
1366-
return;
1367-
}
1353+
VFS_BUG_ON(mnt->mnt_ns);
13681354
lock_mount_hash();
13691355
/*
13701356
* make sure that if __legitimize_mnt() has not seen us grab
@@ -1415,6 +1401,26 @@ static void mntput_no_expire(struct mount *mnt)
14151401
cleanup_mnt(mnt);
14161402
}
14171403

1404+
static void mntput_no_expire(struct mount *mnt)
1405+
{
1406+
rcu_read_lock();
1407+
if (likely(READ_ONCE(mnt->mnt_ns))) {
1408+
/*
1409+
* Since we don't do lock_mount_hash() here,
1410+
* ->mnt_ns can change under us. However, if it's
1411+
* non-NULL, then there's a reference that won't
1412+
* be dropped until after an RCU delay done after
1413+
* turning ->mnt_ns NULL. So if we observe it
1414+
* non-NULL under rcu_read_lock(), the reference
1415+
* we are dropping is not the final one.
1416+
*/
1417+
mnt_add_count(mnt, -1);
1418+
rcu_read_unlock();
1419+
return;
1420+
}
1421+
mntput_no_expire_slowpath(mnt);
1422+
}
1423+
14181424
void mntput(struct vfsmount *mnt)
14191425
{
14201426
if (mnt) {

0 commit comments

Comments
 (0)