* [PATCH v4 0/3] fs/resctrl: Fix RMID limbo handling
@ 2026-11-05 7:09 Jinjie Ruan
2026-11-05 7:09 ` [PATCH v4 1/3] fs/resctrl: Report a temporary RMID shortage per CLOSID Jinjie Ruan
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Jinjie Ruan @ 2026-11-05 7:09 UTC (permalink / raw)
To: tony.luck, reinette.chatre, Dave.Martin, james.morse, babu.moger,
bp, tan.shaopeng, zengheng4, gshan, jic23, ben.horgan, x86,
linux-kernel
Cc: ruanjinjie
Fix resctrl RMID allocation to report a retryable -EBUSY only when
the target CLOSID actually has RMIDs in limbo.
Split the domain-offline path out so it releases busy RMIDs without
allocating a monitor context it never uses.
Also unmount resctrl with the CDP state it was mounted with to fix
another bug with mpam cdp.
These fixes are split out of the v10 Narrow-PARTID series below.
https://lore.kernel.org/all/20261020134239.3921377-1-ruanjinjie@huawei.com/
Changes in v4:
- Fix the unmount resctrl bug as Reinette suggested.
- Adjust the commit message.
- Add Reviewed-bys.
- Link to v3:
- https://lore.kernel.org/all/20261031063634.1678345-1-ruanjinjie@huawei.com/
- https://lore.kernel.org/all/20261031094616.1691026-1-ruanjinjie@huawei.com/
Changes in v3:
- Add Reviewed-by.
- Local varibles uses reverse Christmas tree style.
- Update the commit message as Reinette suggested.
- Link to v2: https://lore.kernel.org/all/20261030092144.1233551-1-ruanjinjie@huawei.com/
Changes in v2
- Update the commit message as Reinette suggested.
- Link to v1: https://lore.kernel.org/all/20261029081513.924019-1-ruanjinjie@huawei.com/
Jinjie Ruan (3):
fs/resctrl: Report a temporary RMID shortage per CLOSID
fs/resctrl: Do not allocate a monitor context when releasing limbo
RMIDs
fs/resctrl: Unmount resctrl with the CDP state it was mounted with
fs/resctrl/internal.h | 3 +-
fs/resctrl/monitor.c | 158 ++++++++++++++++++++++++++++++++----------
fs/resctrl/rdtgroup.c | 9 ++-
3 files changed, 130 insertions(+), 40 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v4 1/3] fs/resctrl: Report a temporary RMID shortage per CLOSID
2026-11-05 7:09 [PATCH v4 0/3] fs/resctrl: Fix RMID limbo handling Jinjie Ruan
@ 2026-11-05 7:09 ` Jinjie Ruan
2026-11-05 11:26 ` Ben Horgan
2026-11-05 7:09 ` [PATCH v4 2/3] fs/resctrl: Do not allocate a monitor context when releasing limbo RMIDs Jinjie Ruan
2026-11-05 7:09 ` [PATCH v4 3/3] fs/resctrl: Unmount resctrl with the CDP state it was mounted with Jinjie Ruan
2 siblings, 1 reply; 5+ messages in thread
From: Jinjie Ruan @ 2026-11-05 7:09 UTC (permalink / raw)
To: tony.luck, reinette.chatre, Dave.Martin, james.morse, babu.moger,
bp, tan.shaopeng, zengheng4, gshan, jic23, ben.horgan, x86,
linux-kernel
Cc: ruanjinjie
An RMID that is freed is held in limbo until its cache occupancy drops
below the threshold, after which it returns to the free list. A request
that fails because of limbo is thus temporary and worth retrying, which
resctrl reports to userspace as -EBUSY. A request that fails because
every RMID is in use is permanent and reported as -ENOSPC.
Where an RMID is only meaningful together with a CLOSID, a request can
only be satisfied by an RMID belonging to the requested CLOSID, so the
distinction has to be drawn per CLOSID. Instead it is drawn system wide.
-ENOSPC is reported when the free list holds no RMID for the requested
CLOSID, even when that CLOSID has RMIDs in limbo. -EBUSY is reported
when the free list is empty and another CLOSID has an RMID in limbo,
even when the requested CLOSID has none. Userspace is thus told to give
up on a shortage that may clear on its own, and to retry one that cannot
clear until it removes a group itself.
Architectures where the RMID is independent of the CLOSID always match
the first entry on the free list, so neither case arises there and only
MPAM systems are affected.
Draw the distinction from the number of RMIDs the requested CLOSID has
in limbo where the RMID depends on the CLOSID, and from the system wide
count otherwise. Drop the separate test for an empty free list, which
the search handles on its own.
Fixes: c4c0376eefe1 ("x86/resctrl: Allow RMID allocation to be scoped by CLOSID")
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
Reviewed-by: Reinette Chatre <reinette.chatre@intel.com>
Cc: James Morse <james.morse@arm.com>
Cc: Reinette Chatre <reinette.chatre@intel.com>
Cc: Babu Moger <babu.moger@amd.com>
Cc: <stable@vger.kernel.org> # 7.1.x
---
fs/resctrl/monitor.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c
index 04e4ea612b7c..b8f4e1ff4083 100644
--- a/fs/resctrl/monitor.c
+++ b/fs/resctrl/monitor.c
@@ -207,9 +207,6 @@ static struct rmid_entry *resctrl_find_free_rmid(u32 closid)
struct rmid_entry *itr;
u32 itr_idx, cmp_idx;
- if (list_empty(&rmid_free_lru))
- return rmid_limbo_count ? ERR_PTR(-EBUSY) : ERR_PTR(-ENOSPC);
-
list_for_each_entry(itr, &rmid_free_lru, list) {
/*
* Get the index of this free RMID, and the index it would need
@@ -225,7 +222,17 @@ static struct rmid_entry *resctrl_find_free_rmid(u32 closid)
return itr;
}
- return ERR_PTR(-ENOSPC);
+ /*
+ * No free RMID matched. If this CLOSID has RMIDs in limbo, return
+ * -EBUSY so userspace can retry. Otherwise, the CLOSID is genuinely
+ * out of RMIDs. When RMIDs are not per-CLOSID, any RMID in limbo
+ * delays the allocation.
+ */
+ if (IS_ENABLED(CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID))
+ return closid_num_dirty_rmid[closid] ? ERR_PTR(-EBUSY) :
+ ERR_PTR(-ENOSPC);
+
+ return rmid_limbo_count ? ERR_PTR(-EBUSY) : ERR_PTR(-ENOSPC);
}
/**
--
2.34.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v4 2/3] fs/resctrl: Do not allocate a monitor context when releasing limbo RMIDs
2026-11-05 7:09 [PATCH v4 0/3] fs/resctrl: Fix RMID limbo handling Jinjie Ruan
2026-11-05 7:09 ` [PATCH v4 1/3] fs/resctrl: Report a temporary RMID shortage per CLOSID Jinjie Ruan
@ 2026-11-05 7:09 ` Jinjie Ruan
2026-11-05 7:09 ` [PATCH v4 3/3] fs/resctrl: Unmount resctrl with the CDP state it was mounted with Jinjie Ruan
2 siblings, 0 replies; 5+ messages in thread
From: Jinjie Ruan @ 2026-11-05 7:09 UTC (permalink / raw)
To: tony.luck, reinette.chatre, Dave.Martin, james.morse, babu.moger,
bp, tan.shaopeng, zengheng4, gshan, jic23, ben.horgan, x86,
linux-kernel
Cc: ruanjinjie
Busy RMIDs of a monitor domain are normally released by the limbo
handler once their cache occupancy drops below the threshold. When a
domain goes offline, its busy RMIDs are released without checking
occupancy, since the domain is going away and the RMIDs would otherwise
never return to the free list.
On the monitor domain offline path, __check_limbo() allocates the
monitor context that an occupancy check needs before it scans the busy
RMIDs, but without using it, and returns early when that allocation
fails. Then the caller destroys the domain's monitoring state, including
the bitmap that records which RMIDs are busy, so nothing can clear those
bits afterwards and the busy counts never reach zero. Those RMIDs never
return to the free list and, where the RMID depends on the CLOSID, the
dirty count of their CLOSID never decreases. The allocation can also
wait for a monitor to become free, which stalls the CPU offline path on
a context that is not going to be used.
Only MPAM systems are affected. An architecture that can always read an
RMID allocates nothing for the monitor context, so the allocation can
neither fail nor wait there.
Move the release of busy RMIDs into a separate function that does not
take a monitor context and leave the occupancy check to __check_limbo().
Fixes: e557999f80a5 ("x86/resctrl: Allow arch to allocate memory needed in resctrl_arch_rmid_read()")
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
Reviewed-by: Reinette Chatre <reinette.chatre@intel.com>
Cc: James Morse <james.morse@arm.com>
Cc: Reinette Chatre <reinette.chatre@intel.com>
Cc: <stable@vger.kernel.org> # 7.1.x
---
fs/resctrl/internal.h | 2 +-
fs/resctrl/monitor.c | 72 ++++++++++++++++++++++++++++---------------
fs/resctrl/rdtgroup.c | 2 +-
3 files changed, 49 insertions(+), 27 deletions(-)
diff --git a/fs/resctrl/internal.h b/fs/resctrl/internal.h
index e62a277dee85..1c85e06f09bf 100644
--- a/fs/resctrl/internal.h
+++ b/fs/resctrl/internal.h
@@ -405,7 +405,7 @@ void cqm_handle_limbo(struct work_struct *work);
bool has_busy_rmid(struct rdt_l3_mon_domain *d);
-void __check_limbo(struct rdt_l3_mon_domain *d, bool force_free);
+void release_limbo_rmids(struct rdt_l3_mon_domain *d);
void resctrl_file_fflags_init(const char *config, unsigned long fflags);
diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c
index b8f4e1ff4083..ae9ddd380515 100644
--- a/fs/resctrl/monitor.c
+++ b/fs/resctrl/monitor.c
@@ -124,21 +124,45 @@ static void limbo_release_entry(struct rmid_entry *entry)
closid_num_dirty_rmid[entry->closid]--;
}
+/*
+ * Release the RMIDs that are marked as busy for this domain without
+ * checking their LLC occupancy. Cache lines may still be tagged with
+ * these RMIDs and will be accounted to the next user of each RMID.
+ */
+void release_limbo_rmids(struct rdt_l3_mon_domain *d)
+{
+ u32 idx_limit = resctrl_arch_system_num_rmid_idx();
+ struct rmid_entry *entry;
+ u32 idx, cur_idx = 1;
+
+ for (;;) {
+ idx = find_next_bit(d->rmid_busy_llc, idx_limit, cur_idx);
+ if (idx >= idx_limit)
+ break;
+
+ entry = __rmid_entry(idx);
+ clear_bit(idx, d->rmid_busy_llc);
+ if (!--entry->busy)
+ limbo_release_entry(entry);
+ cur_idx = idx + 1;
+ }
+}
+
/*
* Check the RMIDs that are marked as busy for this domain. If the
* reported LLC occupancy is below the threshold clear the busy bit and
* decrement the count. If the busy count gets to zero on an RMID, we
* free the RMID
*/
-void __check_limbo(struct rdt_l3_mon_domain *d, bool force_free)
+static void __check_limbo(struct rdt_l3_mon_domain *d)
{
struct rdt_resource *r = resctrl_arch_get_resource(RDT_RESOURCE_L3);
u32 idx_limit = resctrl_arch_system_num_rmid_idx();
struct rmid_entry *entry;
- bool rmid_dirty = true;
u32 idx, cur_idx = 1;
void *arch_mon_ctx;
void *arch_priv;
+ bool rmid_dirty;
u64 val = 0;
arch_priv = mon_event_all[QOS_L3_OCCUP_EVENT_ID].arch_priv;
@@ -161,30 +185,28 @@ void __check_limbo(struct rdt_l3_mon_domain *d, bool force_free)
break;
entry = __rmid_entry(idx);
- if (!force_free) {
- if (resctrl_arch_rmid_read(r, &d->hdr, entry->closid,
- entry->rmid, QOS_L3_OCCUP_EVENT_ID,
- arch_priv, &val, arch_mon_ctx)) {
- rmid_dirty = true;
- } else {
- rmid_dirty = (val >= resctrl_rmid_realloc_threshold);
-
- /*
- * x86's CLOSID and RMID are independent numbers,
- * so the entry's CLOSID is an empty CLOSID
- * (X86_RESCTRL_EMPTY_CLOSID). On Arm the RMID
- * (PMG) extends the CLOSID (PARTID) space with
- * bits that aren't used to select the configuration.
- * It is thus necessary to track both CLOSID and
- * RMID because there may be dependencies between
- * them on some architectures.
- */
- trace_mon_llc_occupancy_limbo(entry->closid, entry->rmid,
- d->hdr.id, val);
- }
+ if (resctrl_arch_rmid_read(r, &d->hdr, entry->closid,
+ entry->rmid, QOS_L3_OCCUP_EVENT_ID,
+ arch_priv, &val, arch_mon_ctx)) {
+ rmid_dirty = true;
+ } else {
+ rmid_dirty = (val >= resctrl_rmid_realloc_threshold);
+
+ /*
+ * x86's CLOSID and RMID are independent numbers,
+ * so the entry's CLOSID is an empty CLOSID
+ * (X86_RESCTRL_EMPTY_CLOSID). On Arm the RMID
+ * (PMG) extends the CLOSID (PARTID) space with
+ * bits that aren't used to select the configuration.
+ * It is thus necessary to track both CLOSID and
+ * RMID because there may be dependencies between
+ * them on some architectures.
+ */
+ trace_mon_llc_occupancy_limbo(entry->closid, entry->rmid,
+ d->hdr.id, val);
}
- if (force_free || !rmid_dirty) {
+ if (!rmid_dirty) {
clear_bit(idx, d->rmid_busy_llc);
if (!--entry->busy)
limbo_release_entry(entry);
@@ -843,7 +865,7 @@ void cqm_handle_limbo(struct work_struct *work)
if (cpumask_empty(&d->hdr.cpu_mask))
goto out_unlock;
- __check_limbo(d, false);
+ __check_limbo(d);
if (has_busy_rmid(d)) {
d->cqm_work_cpu = cpumask_any_housekeeping(&d->hdr.cpu_mask,
diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c
index 57ab090072c2..5d0351453c2f 100644
--- a/fs/resctrl/rdtgroup.c
+++ b/fs/resctrl/rdtgroup.c
@@ -4590,7 +4590,7 @@ void resctrl_offline_mon_domain(struct rdt_resource *r, struct rdt_domain_hdr *h
* the RMID as busy creates RMID leaks if the
* package never comes back.
*/
- __check_limbo(d, true);
+ release_limbo_rmids(d);
}
domain_destroy_l3_mon_state(d);
--
2.34.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v4 3/3] fs/resctrl: Unmount resctrl with the CDP state it was mounted with
2026-11-05 7:09 [PATCH v4 0/3] fs/resctrl: Fix RMID limbo handling Jinjie Ruan
2026-11-05 7:09 ` [PATCH v4 1/3] fs/resctrl: Report a temporary RMID shortage per CLOSID Jinjie Ruan
2026-11-05 7:09 ` [PATCH v4 2/3] fs/resctrl: Do not allocate a monitor context when releasing limbo RMIDs Jinjie Ruan
@ 2026-11-05 7:09 ` Jinjie Ruan
2 siblings, 0 replies; 5+ messages in thread
From: Jinjie Ruan @ 2026-11-05 7:09 UTC (permalink / raw)
To: tony.luck, reinette.chatre, Dave.Martin, james.morse, babu.moger,
bp, tan.shaopeng, zengheng4, gshan, jic23, ben.horgan, x86,
linux-kernel
Cc: ruanjinjie
resctrl can be mounted without CDP, unmounted, and mounted again with
CDP enabled. A group's RMID is not returned to the free list when the
group is removed: it stays in limbo until the cache lines tagged with it
are evicted, and a limbo worker reads its occupancy counter in the
meantime. When resctrl is mounted again, the worker reads the RMIDs of
the groups removed by the unmount.
On MPAM the counter is selected by the PARTID of the CLOSID that owned
the RMID. Without CDP, CLOSID c is PARTID c; with CDP it is PARTIDs 2c
and 2c+1. resctrl_unmount() clears the CDP state before it removes the
groups, so their monitor configuration is also removed with a different
CLOSID to PARTID mapping. With 5 PARTIDs:
mount CDP off, CLOSID c -> PARTID c
mkdir g1..g4 CLOSIDs 1..4
umount
rdt_disable_ctx() clear CDP
remove g1..g4 RMIDs enter limbo with CLOSIDs 1..4
mount -o cdp CDP on, CLOSID c -> PARTIDs 2c, 2c+1
limbo worker reads CLOSID 2 as PARTID 5 > PARTID_MAX 4
MSC error interrupt, mpam_disable()
The groups are removed after rdt_disable_ctx() clears CDP, so their
monitor configuration is cleared with a CLOSID to PARTID mapping that
differs from the one used to set it up.
Clear the CDP state after the groups are removed. While resctrl is
unmounted, don't read the RMIDs in limbo. When resctrl is mounted,
return the RMIDs freed under the other CDP state to the free list
without reading their counters, then restart the limbo worker unless it
is already queued. The RMIDs stay in limbo across the unmount so that a
quick remount does not give a new group an RMID that cache lines from
the removed group still carry.
Only MPAM with CDP enabled through the cdp or cdpl2 mount option is
affected; CDP depends on CONFIG_EXPERT. x86 is not affected as its RMID
does not depend on the CLOSID.
Reproduced on QEMU with the sequence above:
mpam:__mpam_irq_handler: error irq from msc:1 'MSMONCFG_ID_RANGE', partid:5, pmg: 0, ris: 0
mpam:mpam_disable: MPAM disabled due to hardware error interrupt
With the change the sequence completes without an error.
Fixes: 6789fb99282c ("arm_mpam: resctrl: Add CDP emulation")
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
Suggested-by: Ben Horgan <ben.horgan@arm.com>
Suggested-by: Reinette Chatre <reinette.chatre@intel.com>
Cc: <stable@vger.kernel.org> # 7.1+
Cc: Tony Luck <tony.luck@intel.com>
Cc: Reinette Chatre <reinette.chatre@intel.com>
Cc: Dave Martin <Dave.Martin@arm.com>
Cc: James Morse <james.morse@arm.com>
Cc: Babu Moger <babu.moger@amd.com>
Link: https://lore.kernel.org/all/20261020134239.3921377-7-ruanjinjie@huawei.com/
---
v4:
- Use resctrl_mounted instead of a separate limbo_paused flag, as the MBM
overflow handler does.
- Record the CDP state once when resctrl is mounted instead of on every
RMID that is freed.
- Add resctrl_limbo_resume(), called once resctrl_mounted is set.
- Treat CDP enabled on either cache as a change of the CDP state.
- Only release RMIDs where the RMID depends on the CLOSID, and skip
domains that have no occupancy bitmap.
- Restart the limbo worker only when it is not already queued.
- Start the limbo handler without a delay.
- Update cqm_work_cpu only when schedule_delayed_work_on() queued the
work, so it always names the CPU the work is queued on.
- Previous Link: https://lore.kernel.org/all/20261031094616.1691026-1-ruanjinjie@huawei.com/
---
fs/resctrl/internal.h | 1 +
fs/resctrl/monitor.c | 71 ++++++++++++++++++++++++++++++++++++++-----
fs/resctrl/rdtgroup.c | 7 +++--
3 files changed, 70 insertions(+), 9 deletions(-)
diff --git a/fs/resctrl/internal.h b/fs/resctrl/internal.h
index 1c85e06f09bf..c95fa6ce62e6 100644
--- a/fs/resctrl/internal.h
+++ b/fs/resctrl/internal.h
@@ -373,6 +373,7 @@ void closid_free(int closid);
int setup_rmid_lru_list(void);
void free_rmid_lru_list(void);
+void resctrl_limbo_resume(void);
int alloc_rmid(u32 closid);
diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c
index ae9ddd380515..717c3888c2b5 100644
--- a/fs/resctrl/monitor.c
+++ b/fs/resctrl/monitor.c
@@ -70,6 +70,11 @@ static u32 *closid_num_dirty_rmid;
*/
static unsigned int rmid_limbo_count;
+/*
+ * @limbo_cdp - The CDP state under which the RMIDs in limbo were freed.
+ */
+static bool limbo_cdp;
+
/*
* @rmid_entry - The entry in the limbo and free lists.
*/
@@ -852,6 +857,10 @@ void cqm_handle_limbo(struct work_struct *work)
*/
mutex_lock(&rdtgroup_mutex);
+ /* Don't read the RMIDs in limbo until a mount sets up the CDP state. */
+ if (IS_ENABLED(CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID) && !resctrl_mounted)
+ goto out_unlock;
+
/*
* Ensure the worker is dedicated to a CPU as intended and not
* relocated by workqueue subsystem as part of CPU going offline.
@@ -868,10 +877,12 @@ void cqm_handle_limbo(struct work_struct *work)
__check_limbo(d);
if (has_busy_rmid(d)) {
- d->cqm_work_cpu = cpumask_any_housekeeping(&d->hdr.cpu_mask,
- RESCTRL_PICK_ANY_CPU);
- schedule_delayed_work_on(d->cqm_work_cpu, &d->cqm_limbo,
- delay);
+ int cpu;
+
+ cpu = cpumask_any_housekeeping(&d->hdr.cpu_mask,
+ RESCTRL_PICK_ANY_CPU);
+ if (schedule_delayed_work_on(cpu, &d->cqm_limbo, delay))
+ d->cqm_work_cpu = cpu;
}
out_unlock:
@@ -893,10 +904,13 @@ void cqm_setup_limbo_handler(struct rdt_l3_mon_domain *dom, unsigned long delay_
int cpu;
cpu = cpumask_any_housekeeping(&dom->hdr.cpu_mask, exclude_cpu);
- dom->cqm_work_cpu = cpu;
+ if (cpu >= nr_cpu_ids) {
+ dom->cqm_work_cpu = cpu;
+ return;
+ }
- if (cpu < nr_cpu_ids)
- schedule_delayed_work_on(cpu, &dom->cqm_limbo, delay);
+ if (schedule_delayed_work_on(cpu, &dom->cqm_limbo, delay))
+ dom->cqm_work_cpu = cpu;
}
void mbm_handle_overflow(struct work_struct *work)
@@ -1033,6 +1047,49 @@ int setup_rmid_lru_list(void)
return 0;
}
+/**
+ * resctrl_limbo_resume() - Resume RMID limbo handling after a mount.
+ *
+ * Release the RMIDs that were freed under another CDP state without
+ * reading them, and restart the limbo handler.
+ */
+void resctrl_limbo_resume(void)
+{
+ struct rdt_l3_mon_domain *d;
+ struct rdt_resource *r;
+ bool cdp;
+
+ if (!IS_ENABLED(CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID) ||
+ !resctrl_arch_mon_capable())
+ return;
+
+ lockdep_assert_held(&rdtgroup_mutex);
+
+ r = resctrl_arch_get_resource(RDT_RESOURCE_L3);
+
+ cdp = resctrl_arch_get_cdp_enabled(RDT_RESOURCE_L2) ||
+ resctrl_arch_get_cdp_enabled(RDT_RESOURCE_L3);
+
+ if (cdp != limbo_cdp) {
+ list_for_each_entry_rcu(d, &r->mon_domains, hdr.list,
+ lockdep_is_cpus_held()) {
+ if (d->rmid_busy_llc && has_busy_rmid(d))
+ release_limbo_rmids(d);
+ }
+ }
+ limbo_cdp = cdp;
+
+ if (!resctrl_is_mon_event_enabled(QOS_L3_OCCUP_EVENT_ID))
+ return;
+
+ list_for_each_entry_rcu(d, &r->mon_domains, hdr.list,
+ lockdep_is_cpus_held()) {
+ /* A queued worker will run, don't move its cqm_work_cpu. */
+ if (has_busy_rmid(d) && !delayed_work_pending(&d->cqm_limbo))
+ cqm_setup_limbo_handler(d, 0, RESCTRL_PICK_ANY_CPU);
+ }
+}
+
void free_rmid_lru_list(void)
{
if (!resctrl_arch_mon_capable())
diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c
index 5d0351453c2f..e6b64a5c9302 100644
--- a/fs/resctrl/rdtgroup.c
+++ b/fs/resctrl/rdtgroup.c
@@ -3150,13 +3150,14 @@ static void resctrl_unmount(void)
cpus_read_lock();
mutex_lock(&rdtgroup_mutex);
- rdt_disable_ctx();
-
/* Put everything back to default values. */
for_each_alloc_capable_rdt_resource(r)
resctrl_arch_reset_all_ctrls(r);
resctrl_fs_teardown();
+
+ /* Remove the groups under the CDP state they were set up with. */
+ rdt_disable_ctx();
if (resctrl_arch_alloc_capable())
resctrl_arch_disable_alloc();
if (resctrl_arch_mon_capable())
@@ -3261,6 +3262,8 @@ static int rdt_get_tree(struct fs_context *fc)
RESCTRL_PICK_ANY_CPU);
}
+ resctrl_limbo_resume();
+
/*
* Ensure root remains accessible after mutex is unlocked so that
* kernfs_kill_sb() can run safely if called by kernfs_get_tree()'s
--
2.34.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v4 1/3] fs/resctrl: Report a temporary RMID shortage per CLOSID
2026-11-05 7:09 ` [PATCH v4 1/3] fs/resctrl: Report a temporary RMID shortage per CLOSID Jinjie Ruan
@ 2026-11-05 11:26 ` Ben Horgan
0 siblings, 0 replies; 5+ messages in thread
From: Ben Horgan @ 2026-11-05 11:26 UTC (permalink / raw)
To: Jinjie Ruan, tony.luck, reinette.chatre, Dave.Martin,
james.morse, babu.moger, bp, tan.shaopeng, zengheng4, gshan,
jic23, x86, linux-kernel
Hi Jinjie,
On 05/11/2026 07:09, Jinjie Ruan wrote:
> An RMID that is freed is held in limbo until its cache occupancy drops
> below the threshold, after which it returns to the free list. A request
> that fails because of limbo is thus temporary and worth retrying, which
> resctrl reports to userspace as -EBUSY. A request that fails because
> every RMID is in use is permanent and reported as -ENOSPC.
>
> Where an RMID is only meaningful together with a CLOSID, a request can
> only be satisfied by an RMID belonging to the requested CLOSID, so the
> distinction has to be drawn per CLOSID. Instead it is drawn system wide.
> -ENOSPC is reported when the free list holds no RMID for the requested
> CLOSID, even when that CLOSID has RMIDs in limbo. -EBUSY is reported
> when the free list is empty and another CLOSID has an RMID in limbo,
> even when the requested CLOSID has none. Userspace is thus told to give
> up on a shortage that may clear on its own, and to retry one that cannot
> clear until it removes a group itself.
>
> Architectures where the RMID is independent of the CLOSID always match
> the first entry on the free list, so neither case arises there and only
> MPAM systems are affected.
>
> Draw the distinction from the number of RMIDs the requested CLOSID has
> in limbo where the RMID depends on the CLOSID, and from the system wide
> count otherwise. Drop the separate test for an empty free list, which
> the search handles on its own.
>
> Fixes: c4c0376eefe1 ("x86/resctrl: Allow RMID allocation to be scoped by CLOSID")
> Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
> Reviewed-by: Reinette Chatre <reinette.chatre@intel.com>
Thanks for fixing this MPAM oversight.
Reviewed-by: Ben Horgan <ben.horgan@arm.com>
> Cc: James Morse <james.morse@arm.com>
> Cc: Reinette Chatre <reinette.chatre@intel.com>
> Cc: Babu Moger <babu.moger@amd.com>
> Cc: <stable@vger.kernel.org> # 7.1.x
> ---
> fs/resctrl/monitor.c | 15 +++++++++++----
> 1 file changed, 11 insertions(+), 4 deletions(-)
>
> diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c
> index 04e4ea612b7c..b8f4e1ff4083 100644
> --- a/fs/resctrl/monitor.c
> +++ b/fs/resctrl/monitor.c
> @@ -207,9 +207,6 @@ static struct rmid_entry *resctrl_find_free_rmid(u32 closid)
> struct rmid_entry *itr;
> u32 itr_idx, cmp_idx;
>
> - if (list_empty(&rmid_free_lru))
> - return rmid_limbo_count ? ERR_PTR(-EBUSY) : ERR_PTR(-ENOSPC);
> -
> list_for_each_entry(itr, &rmid_free_lru, list) {
> /*
> * Get the index of this free RMID, and the index it would need
> @@ -225,7 +222,17 @@ static struct rmid_entry *resctrl_find_free_rmid(u32 closid)
> return itr;
> }
>
> - return ERR_PTR(-ENOSPC);
> + /*
> + * No free RMID matched. If this CLOSID has RMIDs in limbo, return
> + * -EBUSY so userspace can retry. Otherwise, the CLOSID is genuinely
> + * out of RMIDs. When RMIDs are not per-CLOSID, any RMID in limbo
> + * delays the allocation.
> + */
> + if (IS_ENABLED(CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID))
> + return closid_num_dirty_rmid[closid] ? ERR_PTR(-EBUSY) :
> + ERR_PTR(-ENOSPC);
> +
> + return rmid_limbo_count ? ERR_PTR(-EBUSY) : ERR_PTR(-ENOSPC);
> }
>
> /**
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-11-05 11:26 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-05 7:09 [PATCH v4 0/3] fs/resctrl: Fix RMID limbo handling Jinjie Ruan
2026-11-05 7:09 ` [PATCH v4 1/3] fs/resctrl: Report a temporary RMID shortage per CLOSID Jinjie Ruan
2026-11-05 11:26 ` Ben Horgan
2026-11-05 7:09 ` [PATCH v4 2/3] fs/resctrl: Do not allocate a monitor context when releasing limbo RMIDs Jinjie Ruan
2026-11-05 7:09 ` [PATCH v4 3/3] fs/resctrl: Unmount resctrl with the CDP state it was mounted with Jinjie Ruan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®