mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Jinjie Ruan <ruanjinjie@huawei.com>
To: Reinette Chatre <reinette.chatre@intel.com>,
	<tony.luck@intel.com>, <Dave.Martin@arm.com>,
	<james.morse@arm.com>, <babu.moger@amd.com>, <jic23@kernel.org>,
	<ben.horgan@arm.com>, <zengheng4@huawei.com>, <gshan@redhat.com>,
	<x86@kernel.org>, <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH] fs/resctrl: Unmount resctrl with the CDP state it was mounted with
Date: Thu, 5 Nov 2026 14:54:30 +0800	[thread overview]
Message-ID: <2c2db850-071e-4121-8892-8f4a568d19cd@huawei.com> (raw)
In-Reply-To: <71a65c26-da2f-469c-a38a-4b6b279ead96@intel.com>



在 2026/11/3 13:51, Reinette Chatre 写道:
> Hi Jinjie,
> 
> On 10/31/26 2:46 AM, Jinjie Ruan wrote:
>> Busy RMIDs of a monitor domain are normally released by the limbo handler
>> once their cache occupancy drops below the threshold. The handler keeps
>> running after resctrl is unmounted, and  each RMID left in limbo retains
>> the CLOSID it was allocated with.
>>
>> When reading the counter for an RMID in limbo, the architecture translates
>> the CLOSID associated with that RMID into a PARTID. On arm64 MPAM with CDP
>> enabled, CLOSID c maps to data PARTID 2 * c and code PARTID 2 * c + 1,
>> so the same CLOSID selects a different PARTID depending on the CDP state.
>> resctrl_unmount() clears the CDP state before resctrl_fs_teardown() frees
>> the groups, so an RMID left in limbo is read using the CDP state of the
>> next mount rather than the state it was allocated under. A CLOSID from the
>> upper half of the range then produces a PARTID beyond the MSC's range; the
>> MSC raises an MPAM error interrupt, and mpam_disable() disables MPAM.
> 
> Could you please start the problem description with a brief description of the
> scenario? As it is written it is not clear what is meant with "the next mount".

Hi Reinette,

The original question is as follows, I will make it more clear:

https://lore.kernel.org/all/20261020134239.3921377-7-ruanjinjie@huawei.com/

I will add a question sequence diagram.

> 
>>
>> Move the CDP disable after the groups have been torn down, so every
>> CLOSID freed on unmount is translated with the CDP state it was
>> allocated under.
> 
> Above is a brief statement that appears unrelated to earlier problem description.
> Does it aim to capture some other problems encountered with existing rdt_disable_ctx()
> placement? I think MPAM is fortunate that it does not use CLOSID in 

You are right! It means move rdt_disable_ctx() down because
rdt_disable_ctx() changes the cdp state which used in rmdir_all_sub()
and resctrl_fs_teardown() for freeing RMIDs.

> resctrl_arch_reset_all_ctrls() but from what I can tell the per-resource group
> rdtgroup_unassign_cntrs() may also end up leaving stale monitor configuration
> behind?
> 
>> Keep the RMIDs in limbo instead of forcing them back
>> to the free list, because a quick remount would otherwise reuse RMIDs
>> whose counters are still dirty. Pause the limbo handler while the
>> filesystem is unmounted. At mount, release any RMID left in limbo under
>> a different CDP state without reading its counter, since its CLOSID no
>> longer selects the same PARTID, and restart the handler.
> 
> Sounds reasonable.
> 
>>
>> x86 RMIDs are independent of the CLOSID, so the CDP state does not
>> change which counter is read. Only arm64 MPAM systems are affected, and
>> only when CDP is enabled with the cdp mount option (CDP depends on
>> CONFIG_EXPERT).
>>
>> Reproduced on QEMU:
>> - mount resctrl, create four control groups
>> - unmount, and mount again with -o cdp.
>>
>> Before this patch, the limbo handler reads the counters for the limbo RMIDs
> 
> (nit: please never use the "this patch" term in a changelog - this is by definition
> a patch and this term can be a trigger word for some).

Has deleted them.

> 
>> using the doubled PARTID:
>>
>> 	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
>>
>> After this patch the RMIDs are released before their counters are read, and
>> the same sequence completes without an error.
>>
>> Rebased on the below fix.
>> 	https://lore.kernel.org/all/20261031063634.1678345-3-ruanjinjie@huawei.com/
> 
> Information like above rebase hint should not follow a change into the kernel
> and is best left below the "---".

Will put it below "---".

> 
>>
>> Fixes: 6789fb99282c ("arm_mpam: resctrl: Add CDP emulation")
>> Suggested-by: Ben Horgan <ben.horgan@arm.com>
>> Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
>> Cc: <stable@vger.kernel.org> # 7.3.x
>> 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>
>> ---
>>  fs/resctrl/internal.h |  1 +
>>  fs/resctrl/monitor.c  | 60 ++++++++++++++++++++++++++++++++++++++++---
>>  fs/resctrl/rdtgroup.c | 31 +++++++++++++++++-----
>>  3 files changed, 83 insertions(+), 9 deletions(-)
>>
>> diff --git a/fs/resctrl/internal.h b/fs/resctrl/internal.h
>> index 1c85e06f09bf..ccae796a1489 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_pause(void);
>>  
>>  int alloc_rmid(u32 closid);
>>  
>> diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c
>> index 2002c4af1a5c..292f7f334b4c 100644
>> --- a/fs/resctrl/monitor.c
>> +++ b/fs/resctrl/monitor.c
>> @@ -70,6 +70,16 @@ static u32 *closid_num_dirty_rmid;
>>   */
>>  static unsigned int rmid_limbo_count;
>>  
>> +/*
>> + * @limbo_paused - True if the filesystem is unmounted
>> + *     The limbo handler must not read counters until the next mount has
>> + *     set the CDP state up.
> 
> Is this new flag needed? The description "True if the filesystem is unmounted"
> could be a hint that it could just use the "resctrl_mounted" flag
> similar to how the MBM overflow handler uses it?

Yes, this can also work.

> 
> 
>> + * @limbo_cdp - True if the RMIDs currently in limbo were freed with
>> + *     CDP enabled.
>> + */
>> +static bool limbo_paused;
>> +static bool limbo_cdp;
>> +
>>  /*
>>   * @rmid_entry - The entry in the limbo and free lists.
>>   */
>> @@ -350,6 +360,8 @@ static void add_rmid_to_limbo(struct rmid_entry *entry)
>>  		entry->busy++;
>>  	}
>>  
>> +	if (!rmid_limbo_count)
>> +		limbo_cdp = resctrl_arch_get_cdp_enabled(RDT_RESOURCE_L3);
> 
> CDP state cannot change after resctrl mount so this runtime assignment
> on each RMID state change looks redundant. It could just be set once on
> mount? More on this later but I also think the !rmid_limbo_count assumes

You are right! we only enable cdp when mount and disble cdp when umount.
So set once on mount is fine.

> an MPAM underlying architecture since there the rmid_limbo_count will
> always be reset on a state change during mount. Having limbo_cdp gated
> on rmid_limbo_count being zero may thus not behave the same on all
> architectures.

Understand.

> 
>>  	rmid_limbo_count++;
>>  	if (IS_ENABLED(CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID))
>>  		closid_num_dirty_rmid[entry->closid]++;
>> @@ -852,6 +864,13 @@ void cqm_handle_limbo(struct work_struct *work)
>>  	 */
>>  	mutex_lock(&rdtgroup_mutex);
>>  
>> +	/*
>> +	 * The limbo state is kept across mounts, but can't be read while
>> +	 * the filesystem is unmounted: the CDP state may have changed.
>> +	 */
>> +	if (limbo_paused)
> 
> Could this be if (!resctrl_mounted) instead? Compare with mbm_handle_overflow().

Yes, you are right.

> 
>> +		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.
>> @@ -991,6 +1010,8 @@ void mbm_setup_overflow_handler(struct rdt_l3_mon_domain *dom, unsigned long del
>>  int setup_rmid_lru_list(void)
>>  {
>>  	struct rmid_entry *entry = NULL;
>> +	struct rdt_l3_mon_domain *d;
>> +	struct rdt_resource *r;
>>  	u32 idx_limit;
>>  	u32 idx;
>>  	int i;
>> @@ -1001,11 +1022,37 @@ int setup_rmid_lru_list(void)
>>  	/*
>>  	 * Called on every mount, but the number of RMIDs cannot change
>>  	 * after the first mount, so keep using the same set of rmid_ptrs[]
>> -	 * until resctrl_exit(). Note that the limbo handler continues to
>> -	 * access rmid_ptrs[] after resctrl is unmounted.
>> +	 * until resctrl_exit(). The limbo state is kept too, so that dirty
>> +	 * RMIDs aren't reused after a quick remount.
>>  	 */
>> -	if (rmid_ptrs)
>> +	if (rmid_ptrs) {
>> +		r = resctrl_arch_get_resource(RDT_RESOURCE_L3);
>> +
>> +		/*
>> +		 * An entry freed under a different CDP state can't be read
>> +		 * with the new one: its CLOSID selects a different PARTID.
>> +		 * Release those without reading them.
> 
> Please refrain from adding architecture specific comments in resctrl filesystem code
> that aims to be architecture agnostic. Since MPAM support was added after initial resctrl
> design the "CLOSID" and "RMID" terms are "baked into" resctrl fs with known 
> translations added by architectures. 

OK, will delete the architecture specific comments.

> 
>> +		 */
>> +		if (resctrl_arch_get_cdp_enabled(RDT_RESOURCE_L3) != limbo_cdp) {
> 
> Here I am not so sure since I am very unfamiliar with the MPAM driver. It looks
> like the problematic path in MPAM is gated by a global "cdp_enabled" flag that
> may be set when filesystem is mounted with -o cdpl2? Could this mean that

-o cdp or -o cdpl2

> this test would not accurately capture whether MPAM driver uses the "cdp_enabled"
> flows?

Will add the l2 case.

> 
> Apart from this, should this be gated by a 
> 	if (IS_ENABLED(CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID))
> as well as a check that LLC occupancy is actually enabled?

Yes, should be corrected.>
> (
>  ah - looks like sashiko agrees, could you please also check the sashiko
>  feedback at 
> 	https://sashiko.dev/#/patchset/20261031094616.1691026-1-ruanjinjie%40huawei.com

Will fix it.

> )
> 
> 
>> +			list_for_each_entry(d, &r->mon_domains, hdr.list) {
> 
> list_for_each_entry_rcu()?

ok.

> 
>> +				if (has_busy_rmid(d))
>> +					release_limbo_rmids(d);
>> +			}
>> +		}
>> +
>> +		limbo_paused = false;
>> +
>> +		/* Restart the handler for the domains that are still busy. */
> 
> Switching to resctrl_mounted flag would mean this needs to be started later, after
> the flag is set. Doing so has the benefit of placing it with the code that starts

Yes

> the MBM overflow handler that centralizes the workers.
> 
> Thinking about it more - there seems to be a lot of benefits with such a move and
> may avoid needing to move when setup_rmid_lru_list() is called since removing the
> entries that no longer have matching CDP state only needs to be done before
> starting the worker so this can all be done together, after setting resctrl_mounted?
> 
> Could there perhaps be a new function that initializes limbo_cdp, releases limbo
> RMIDs (if needed), and starts the limbo worker? This function can be called from rdt_get_tree()

Yes, it works.

> after resctrl_mounted is set? I think this could simplify this implementation.

Indeed it is.

> 
> 
>> +		if (resctrl_is_mon_event_enabled(QOS_L3_OCCUP_EVENT_ID)) {
>> +			list_for_each_entry(d, &r->mon_domains, hdr.list) {
> 
> list_for_each_entry_rcu()?
> 
>> +				if (has_busy_rmid(d))
>> +					cqm_setup_limbo_handler(d, CQM_LIMBOCHECK_INTERVAL,
> 
> Why is a delay needed here instead of scheduling it to run immediately? 
> With this delay a user may unnecessarily need to wait a second after mounting resctrl
> before new resource groups can be created?

Will remove the delay.

> 
>> +								RESCTRL_PICK_ANY_CPU);
>> +			}
>> +		}
>> +
>>  		return 0;
>> +	}
>>  
>>  	idx_limit = resctrl_arch_system_num_rmid_idx();
>>  	rmid_ptrs = kzalloc_objs(struct rmid_entry, idx_limit);
> Reinette

-- 
Best regards,
Jinjie


      reply	other threads:[~2026-11-05  6:54 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-31  9:46 Jinjie Ruan
2026-11-03  5:51 ` Reinette Chatre
2026-11-05  6:54   ` Jinjie Ruan [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2c2db850-071e-4121-8892-8f4a568d19cd@huawei.com \
    --to=ruanjinjie@huawei.com \
    --cc=Dave.Martin@arm.com \
    --cc=babu.moger@amd.com \
    --cc=ben.horgan@arm.com \
    --cc=gshan@redhat.com \
    --cc=james.morse@arm.com \
    --cc=jic23@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=reinette.chatre@intel.com \
    --cc=tony.luck@intel.com \
    --cc=x86@kernel.org \
    --cc=zengheng4@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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®