]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
fs: move mntput_no_expire() slowpath into a dedicated routine
authorMateusz Guzik <mjguzik@gmail.com>
Fri, 14 Nov 2025 20:18:03 +0000 (21:18 +0100)
committerChristian Brauner <brauner@kernel.org>
Wed, 19 Nov 2025 13:49:28 +0000 (14:49 +0100)
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>
fs/namespace.c

index d82910f33dc483f2753058bdd1a546bce9caf77b..43191f190ef686130fc71e97461a2d866cc63ac1 100644 (file)
@@ -1345,26 +1345,12 @@ static void delayed_mntput(struct work_struct *unused)
 }
 static DECLARE_DELAYED_WORK(delayed_mntput_work, delayed_mntput);
 
-static void mntput_no_expire(struct mount *mnt)
+static void noinline mntput_no_expire_slowpath(struct mount *mnt)
 {
        LIST_HEAD(list);
        int count;
 
-       rcu_read_lock();
-       if (likely(READ_ONCE(mnt->mnt_ns))) {
-               /*
-                * Since we don't do lock_mount_hash() here,
-                * ->mnt_ns can change under us.  However, if it's
-                * non-NULL, then there's a reference that won't
-                * be dropped until after an RCU delay done after
-                * turning ->mnt_ns NULL.  So if we observe it
-                * non-NULL under rcu_read_lock(), the reference
-                * we are dropping is not the final one.
-                */
-               mnt_add_count(mnt, -1);
-               rcu_read_unlock();
-               return;
-       }
+       VFS_BUG_ON(mnt->mnt_ns);
        lock_mount_hash();
        /*
         * make sure that if __legitimize_mnt() has not seen us grab
@@ -1415,6 +1401,26 @@ static void mntput_no_expire(struct mount *mnt)
        cleanup_mnt(mnt);
 }
 
+static void mntput_no_expire(struct mount *mnt)
+{
+       rcu_read_lock();
+       if (likely(READ_ONCE(mnt->mnt_ns))) {
+               /*
+                * Since we don't do lock_mount_hash() here,
+                * ->mnt_ns can change under us.  However, if it's
+                * non-NULL, then there's a reference that won't
+                * be dropped until after an RCU delay done after
+                * turning ->mnt_ns NULL.  So if we observe it
+                * non-NULL under rcu_read_lock(), the reference
+                * we are dropping is not the final one.
+                */
+               mnt_add_count(mnt, -1);
+               rcu_read_unlock();
+               return;
+       }
+       mntput_no_expire_slowpath(mnt);
+}
+
 void mntput(struct vfsmount *mnt)
 {
        if (mnt) {