[PATCH v11 18/23] fs/resctrl: Call arch code for every mount

From: Tony Luck

Date: Mon Aug 31 2026 - 17:45:36 EST


Linux file system code provides no serialization of mount(2) system
calls. Without such serialization calling resctrl_arch_pre_mount() on
every mount before acquiring rdtgroup_mutex would open up many complex
races between mount and unmount operations.

Add resctrl_mount_lock to provide serialization and protect resctrl_mounted.

Signed-off-by: Tony Luck <tony.luck@xxxxxxxxx>
---
v11:
New patch. Locking at file system level replaces v10 attempt
at locking inside architecture resctrl_arch_pre_mount() and
resctrl_arch_unmount()

fs/resctrl/rdtgroup.c | 28 ++++++++++++++++++++++------
1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c
index 3ac518ed2368..7f09d76dbf8c 100644
--- a/fs/resctrl/rdtgroup.c
+++ b/fs/resctrl/rdtgroup.c
@@ -30,6 +30,9 @@

#include "internal.h"

+/* Mutex protecting resctrl_mounted and mount/unmount operations */
+static DEFINE_MUTEX(resctrl_mount_lock);
+
/* Mutex to protect rdtgroup access. */
DEFINE_MUTEX(rdtgroup_mutex);

@@ -3149,6 +3152,7 @@ static void resctrl_unmount(void)
{
struct rdt_resource *r;

+ mutex_lock(&resctrl_mount_lock);
cpus_read_lock();
mutex_lock(&rdtgroup_mutex);

@@ -3166,6 +3170,8 @@ static void resctrl_unmount(void)
resctrl_mounted = false;
mutex_unlock(&rdtgroup_mutex);
cpus_read_unlock();
+ resctrl_arch_unmount();
+ mutex_unlock(&resctrl_mount_lock);
}

static int rdt_get_tree(struct fs_context *fc)
@@ -3177,24 +3183,27 @@ static int rdt_get_tree(struct fs_context *fc)
struct rdt_resource *r;
int ret;

- DO_ONCE_SLEEPABLE(resctrl_arch_pre_mount);
+ mutex_lock(&resctrl_mount_lock);

- cpus_read_lock();
- mutex_lock(&rdtgroup_mutex);
/*
* resctrl file system can only be mounted once.
*/
if (resctrl_mounted) {
ret = -EBUSY;
- goto out;
+ goto out_mount_unlock;
}

/* Avoid races from pending operations from a previous mount */
if (atomic_read(&rdtgroup_default.waitcount) != 0) {
ret = -EBUSY;
- goto out;
+ goto out_mount_unlock;
}

+ resctrl_arch_pre_mount();
+
+ cpus_read_lock();
+ mutex_lock(&rdtgroup_mutex);
+
if (!resctrl_alloc_capable() && !resctrl_mon_capable()) {
ret = -EINVAL;
goto out;
@@ -3289,6 +3298,8 @@ static int rdt_get_tree(struct fs_context *fc)
mutex_unlock(&rdtgroup_mutex);
cpus_read_unlock();

+ mutex_unlock(&resctrl_mount_lock);
+
ret = kernfs_get_tree(fc);
/*
* resctrl can only be mounted once, new superblock only expected
@@ -3297,7 +3308,8 @@ static int rdt_get_tree(struct fs_context *fc)
if (!ctx->kfc.new_sb_created)
resctrl_unmount();
kernfs_put(rdt_root_kn);
- return ret;
+
+ return 0;

out_mondata:
if (resctrl_mon_capable())
@@ -3318,8 +3330,12 @@ static int rdt_get_tree(struct fs_context *fc)
out_root:
rdtgroup_destroy_root();
out:
+ resctrl_arch_unmount();
mutex_unlock(&rdtgroup_mutex);
cpus_read_unlock();
+out_mount_unlock:
+ mutex_unlock(&resctrl_mount_lock);
+
return ret;
}

--
2.55.0