Re: [PATCH 3/4] fs/resctrl: Fix deadlock for errors during mount
From: Chen, Yu C
Date: Sun May 10 2026 - 09:52:59 EST
Hi Tony,
On 5/9/2026 2:21 AM, Tony Luck wrote:
From: Reinette Chatre <reinette.chatre@xxxxxxxxx>
Sashiko noticed[1] a deadlock in the resctrl mount code.
rdt_get_tree() acquires rdtgroup_mutex before calling kernfs_get_tree(). If
superblock setup fails inside kernfs_get_tree(), the VFS calls kill_sb on
the same thread before the call returns. rdt_kill_sb() unconditionally
attempts to acquire rdtgroup_mutex and deadlock occurs.
Move the call to kernfs_get_tree() outside of locks.
Add resctrl_unmount() helper to keep code consistent between the
rdt_get_tree() failure path and a normal unmount.
If kernfs_get_tree() fails and ctx->kfc.new_sb_created is set, then rdt_kill_sb()
has already been called and no further cleanup is needed.
[ ... ]
+
static int rdt_get_tree(struct fs_context *fc)
{
struct rdt_fs_context *ctx = rdt_fc2context(fc);
@@ -3043,10 +3066,6 @@ static int rdt_get_tree(struct fs_context *fc)
if (ret)
goto out_mondata;
- ret = kernfs_get_tree(fc);
- if (ret < 0)
- goto out_psl;
-
if (resctrl_arch_alloc_capable())
resctrl_arch_enable_alloc();
if (resctrl_arch_mon_capable())
@@ -3062,10 +3081,19 @@ static int rdt_get_tree(struct fs_context *fc)
RESCTRL_PICK_ANY_CPU);
}
- goto out;
+ rdt_last_cmd_clear();
+ mutex_unlock(&rdtgroup_mutex);
+ cpus_read_unlock();
+
+ ret = kernfs_get_tree(fc);
+ /*
+ * resctrl can only be mounted once, new superblock only expected
+ * to be created once.
+ */
I gradually came to understand the purpose of new_sb_created,
and how it indicates whether the resctrl state should be released
or has already been released. Initially, I thought that if ctx->kfc.new_sb_created
is false, this could happen either due to a failure to create a superblock or
a reference to an existing superblock. In the latter case, the code tears
down all resctrl state via resctrl_unmount() while still returning success.
As a result, VFS might complete the mount with an invalid resctrl state.
I later realized this scenario cannot occur, as mounting resctrl twice is
impossible - kernfs_get_tree() will not return 0 in such cases. It might
be worthwhile adding a comment here to clarify the rationale/scenario behind this
for future reference IMO : )
thanks,
Chenyu
+ if (!ctx->kfc.new_sb_created)
+ resctrl_unmount();
+ return ret;