Linux cgroups development
 help / color / mirror / Atom feed
* Re: [PATCH v5 0/9] mm: switch THP shrinker to list_lru
From: Johannes Weiner @ 2026-06-03 11:41 UTC (permalink / raw)
  To: Lance Yang
  Cc: akpm, david, ljs, shakeel.butt, mhocko, david, roman.gushchin,
	muchun.song, qi.zheng, yosry.ahmed, ziy, liam, usama.arif, kas,
	vbabka, ryncsn, zaslonko, gor, baolin.wang, baohua, dev.jain,
	npache, ryan.roberts, cgroups, linux-mm, linux-kernel
In-Reply-To: <20260603044426.54863-1-lance.yang@linux.dev>

On Wed, Jun 03, 2026 at 12:44:26PM +0800, Lance Yang wrote:
> 
> On Tue, Jun 02, 2026 at 05:46:02PM -0400, Johannes Weiner wrote:
> >On Mon, Jun 01, 2026 at 04:36:52PM +0800, Lance Yang wrote:
> >> As the changelog above says, the old queue is per-memcg only, rather
> >> than per-memcg-per-node. So reclaim on one node can still walk the whole
> >> memcg queue and split underused THPs from other nodes in the same memcg.
> >> 
> >> But I think the new one can lose reclaim in the cgroup.memory=nokmem
> >> case ...
> >> 
> >> With nokmem, the deferred shrinker can still run from memcg reclaim,
> >> because it is SHRINKER_NONSLAB. But the list_lru is no longer per-memcg:
> >> 
> >> __list_lru_init() clears memcg_aware,
> >> 
> >> 	if (mem_cgroup_kmem_disabled())
> >> 		memcg_aware = false;
> >> 
> >> so list_lru_from_memcg_idx() falls back to the shared node list:
> >> 
> >> static inline struct list_lru_one *
> >> list_lru_from_memcg_idx(struct list_lru *lru, int nid, int idx)
> >> {
> >> 	if (list_lru_memcg_aware(lru) && idx >= 0) {
> >> [...]
> >> 	}
> >> 	return &lru->node[nid].lru;
> >> }
> >> 
> >> That makes the shrinker bit unreliable. __list_lru_add() still sets the
> >> bit on the memcg passed in, but only when the list goes from empty to
> >> non-empty:
> >> 
> >> bool __list_lru_add(struct list_lru *lru, struct list_lru_one *l,
> >> 		    struct list_head *item, int nid,
> >> 		    struct mem_cgroup *memcg)
> >> {
> >> 	if (list_empty(item)) {
> >> [...]
> >> 		if (!l->nr_items++)
> >> 			set_shrinker_bit(memcg, nid, lru_shrinker_id(lru));
> >> [...]
> >> 		return true;
> >> 	}
> >> 	return false;
> >> }
> >> 
> >> If memcg A adds the first folio, A gets the bit. If memcg B later adds a
> >> folio to the same shared list, B does not get a bit, because the list
> >> was already non-empty.
> >> 
> >> So in the A-first/B-later case, reclaim from B may not call the deferred
> >> shrinker at all. The shared list is scanned from memcg reclaim only if
> >> reclaim runs from the memcg that has the bit, such as A here, or from
> >> global reclaim :)
> >> 
> >> Anyway, only after the shared list is emptied does the next memcg to add
> >> a folio get to be the one with the bit, IIUC :)
> >
> >Sorry for the delay, this took me a bit to think about. The shrinker
> >code is a mess.
> >
> >I read it the same way you do. And this is true for all list_lru users
> >when nokmem is set: we just set random nonsense shrinker bits.
> >
> >HOWEVER, the generic shrinker code fixes that up by IGNORING random
> >shrinker bits like this when !memcg_kmem_online(). And shrinking
> >correctly happens only against the shared root queue when the reclaim
> >iterator walks root_mem_cgroup.
> >
> >HOWEVER, the THP shrinker explicitly sets SHRINKER_NONSLAB, which in
> >turn overrides the previous override. So yes there is a weirdness: we
> >get the root cgroup invocation against the shared queue, and then one
> >more time triggered by that random memcg bit.
> >
> >The most direct fix is to just drop SHRINKER_NONSLAB. It declares
> >independence from kmem, which is no longer true.
> >
> >Cleaning up the shrinker code is left for another day.
> 
> Thanks for working on this!
> 
> Wondering if this fix trades one problem for another, though ...
> 
> Before this series, the deferred split shrinker had a real per-memcg
> queue. Even with cgroup.memory=nokmem, memcg reclaim could still scan
> that memcg's own deferred_split_queue:
> 
> memcg reclaim -> deferred split shrinker -> sc->memcg->deferred_split_queue
> 
> With the fix, nokmem + w/o SHRINKER_NONSLAB falls back to a
> non-memcg-aware shrinker:
> 
> memcg reclaim -> skip deferred split shrinker
> 
> root/global reclaim -> deferred split shrinker -> shared list_lru
> 
> Is that expected? There woud be no memcg-driven deferred split reclaim
> under nokmem, IIUC ...

Yes, this is all correct. list_lru is still inherently tied to the
kmem component of memcg (memcg_kmem_id()).

So without kmem, no isolation. But without kmem, no isolation *for a
lot of stuff*. It's a legacy knob when slab accounting was new and
expensive. But so many things depend on it now, disabling it just
punches a nassive hole into memcg functionality and isolation
coverage. It's not a sanctioned production use flag.

This change is negligible from a memcg semantics POV.

> Not sure what the right fix is, as I am not a memcg expert ...

^ permalink raw reply

* Re: [PATCH v3 3/4] mm/zswap: Add per-memcg stat for proactive writeback
From: Hao Jia @ 2026-06-03 11:29 UTC (permalink / raw)
  To: Nhat Pham
  Cc: akpm, tj, hannes, shakeel.butt, mhocko, yosry, mkoutny,
	chengming.zhou, muchun.song, roman.gushchin, cgroups, linux-mm,
	linux-kernel, linux-doc, Hao Jia
In-Reply-To: <CAKEwX=PcFqmsdFqUnpWxrPkoc1B-1w3CEb0ydK3df0qJGG-mnQ@mail.gmail.com>



On 2026/5/30 04:01, Nhat Pham wrote:
> On Tue, May 26, 2026 at 4:46 AM Hao Jia <jiahao.kernel@gmail.com> wrote:
>>
>> From: Hao Jia <jiahao1@lixiang.com>
>>
>> Currently, zswap writeback can be triggered by either the pool limit
>> being hit or by the proactive writeback mechanism. However, the
>> existing 'zswpwb' metric in memory.stat and /proc/vmstat counts all
>> written back pages, making it difficult to distinguish between pages
>> written back due to the pool limit and those written back proactively.
>>
>> Add a new statistic 'zswpwb_proactive' to memory.stat and /proc/vmstat.
>> This counter tracks the number of pages written back due to proactive
>> writeback. This allows users to better monitor and tune the proactive
>> writeback mechanism.
>>
>> Signed-off-by: Hao Jia <jiahao1@lixiang.com>
>> ---
>>   Documentation/admin-guide/cgroup-v2.rst |  4 +++
>>   include/linux/vm_event_item.h           |  1 +
>>   mm/memcontrol.c                         |  1 +
>>   mm/vmstat.c                             |  1 +
>>   mm/zswap.c                              | 41 ++++++++++++++++++-------
>>   5 files changed, 37 insertions(+), 11 deletions(-)
>>
>> diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
>> index 6564abf0dec5..7d65aef83f7b 100644
>> --- a/Documentation/admin-guide/cgroup-v2.rst
>> +++ b/Documentation/admin-guide/cgroup-v2.rst
>> @@ -1748,6 +1748,10 @@ The following nested keys are defined.
>>            zswpwb
>>                  Number of pages written from zswap to swap.
>>
>> +         zswpwb_proactive
>> +               Number of pages written from zswap to swap by proactive
>> +               writeback. This is a subset of zswpwb.
>> +
> 
> nit: I think this is specifically the zswap_writeback_only mode right?
> 
> Technically, normal proactive reclaim (memory.reclaim) can also hit zswap :)
> 
> Maybe some clarification here?

Thanks for the review. I will clarify this further in the next version.

Thanks,
Hao

^ permalink raw reply

* Re: [PATCH v3 2/4] mm/zswap: Implement proactive writeback
From: Hao Jia @ 2026-06-03 11:27 UTC (permalink / raw)
  To: Yosry Ahmed
  Cc: akpm, tj, hannes, shakeel.butt, mhocko, mkoutny, nphamcs,
	chengming.zhou, muchun.song, roman.gushchin, cgroups, linux-mm,
	linux-kernel, linux-doc, Hao Jia
In-Reply-To: <aho-Z6wshceTAYd9@google.com>



On 2026/5/30 09:37, Yosry Ahmed wrote:
> On Tue, May 26, 2026 at 07:45:59PM +0800, Hao Jia wrote:
>> From: Hao Jia <jiahao1@lixiang.com>
>>
>> Zswap currently writes back pages to backing swap reactively, triggered
>> either by the shrinker or when the pool reaches its size limit. There is
>> no mechanism to control the amount of writeback for a specific memory
>> cgroup. However, users may want to proactively write back zswap pages,
>> e.g., to free up memory for other applications or to prepare for
>> memory-intensive workloads.
>>
>> Introduce a "zswap_writeback_only" key to the memory.reclaim cgroup
>> interface. When specified, this key bypasses standard memory reclaim
>> and exclusively performs proactive zswap writeback up to the requested
>> budget. If omitted, the default reclaim behavior remains unchanged.
>>
>> Example usage:
>>    # Write back 100MB of pages from zswap to the backing swap
>>    echo "100M zswap_writeback_only" > memory.reclaim
>>
>> Note that the actual amount written back may be less than requested due
>> to the zswap second-chance algorithm: referenced entries are rotated on
>> the LRU on the first encounter and only written back on a second pass.
>> If fewer bytes are written back than requested, -EAGAIN is returned,
>> matching the existing memory.reclaim semantics.
>>
>> Internally, extend user_proactive_reclaim() to parse the new
>> "zswap_writeback_only" token and invoke the dedicated handler. Add
>> zswap_proactive_writeback() to walk the target memcg subtree via the
>> per-memcg writeback cursor, draining per-node zswap LRUs through
>> list_lru_walk_one() with the shrink_memcg_cb() callback.
>>
>> Suggested-by: Yosry Ahmed <yosry@kernel.org>
>> Suggested-by: Nhat Pham <nphamcs@gmail.com>
>> Signed-off-by: Hao Jia <jiahao1@lixiang.com>
>> ---
>>   Documentation/admin-guide/cgroup-v2.rst |  18 +++-
>>   Documentation/admin-guide/mm/zswap.rst  |  11 +-
>>   include/linux/zswap.h                   |   7 ++
>>   mm/vmscan.c                             |  14 +++
>>   mm/zswap.c                              | 138 ++++++++++++++++++++++++
>>   5 files changed, 185 insertions(+), 3 deletions(-)
>>
>> diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
>> index 6efd0095ed99..6564abf0dec5 100644
>> --- a/Documentation/admin-guide/cgroup-v2.rst
>> +++ b/Documentation/admin-guide/cgroup-v2.rst
>> @@ -1425,9 +1425,10 @@ PAGE_SIZE multiple when read back.
>>   
>>   The following nested keys are defined.
>>   
>> -	  ==========            ================================
>> +	  ====================  ==================================================
>>   	  swappiness            Swappiness value to reclaim with
>> -	  ==========            ================================
>> +	  zswap_writeback_only  Only perform proactive zswap writeback
>> +	  ====================  ==================================================
>>   
>>   	Specifying a swappiness value instructs the kernel to perform
>>   	the reclaim with that swappiness value. Note that this has the
>> @@ -1437,6 +1438,19 @@ The following nested keys are defined.
>>   	The valid range for swappiness is [0-200, max], setting
>>   	swappiness=max exclusively reclaims anonymous memory.
>>   
>> +	The zswap_writeback_only key skips ordinary memory reclaim and
>> +	writes back pages from zswap to the backing swap device until
>> +	the requested amount has been written or no further candidates
>> +	are found. This is useful to proactively offload cold pages from
>> +	the zswap pool to the swap device. It is only available if
>> +	zswap writeback is enabled. zswap_writeback_only cannot be combined
>> +	with swappiness; specifying both returns -EINVAL.
>> +
>> +	Example::
>> +
>> +	  # Write back up to 100MB of pages from zswap to the backing swap
>> +	  echo "100M zswap_writeback_only" > memory.reclaim
> 
> 
> memcg folks need to chime in about the interface here. An alternative
> would be a separate interface (e.g. memory.zswap.do_writeback or
> memory.zswap.writeback.reclaim or sth).
> 
>> diff --git a/mm/zswap.c b/mm/zswap.c
>> index 73e64a635690..7bcbf788f634 100644
>> --- a/mm/zswap.c
>> +++ b/mm/zswap.c
>> @@ -1679,6 +1679,144 @@ int zswap_load(struct folio *folio)
>>   	return 0;
>>   }
>>   
>> +/*
>> + * Maximum LRU scan limit:
>> + * number of entries to scan per page of remaining budget.
>> + */
>> +#define ZSWAP_PROACTIVE_WB_SCAN_RATIO	16UL
>> +/*
>> + * Batch size for proactive writeback:
>> + * - As the per-memcg writeback target in the outer memcg loop.
>> + * - As the per-walk budget passed to list_lru_walk_one().
>> + */
>> +#define ZSWAP_PROACTIVE_WB_BATCH	128UL
>> +
>> +/*
>> + * Walk the per-node LRUs of @memcg to write back up to @nr_to_write pages.
>> + * Returns the number of pages written back, or -ENOENT if @memcg is a
>> + * zombie or has writeback disabled.
>> + */
>> +static long zswap_proactive_shrink_memcg(struct mem_cgroup *memcg,
>> +					 unsigned long nr_to_write)
>> +{
>> +	unsigned long nr_written = 0;
>> +	int nid;
>> +
>> +	if (!mem_cgroup_zswap_writeback_enabled(memcg))
>> +		return -ENOENT;
>> +
>> +	if (!mem_cgroup_online(memcg))
>> +		return -ENOENT;
>> +
>> +	for_each_node_state(nid, N_NORMAL_MEMORY) {
>> +		bool encountered_page_in_swapcache = false;
>> +		unsigned long nr_to_scan, nr_scanned = 0;
>> +
>> +		/*
>> +		 * Cap by LRU length: bounds rewalks when referenced
>> +		 * entries keep rotating to the tail.
>> +		 */
>> +		nr_to_scan = list_lru_count_one(&zswap_list_lru, nid, memcg);
>> +		if (!nr_to_scan)
>> +			continue;
>> +
>> +		/*
>> +		 * Cap by SCAN_RATIO * remaining budget: bounds scan cost
>> +		 * to the remaining writeback budget.
>> +		 */
>> +		nr_to_scan = min(nr_to_scan,
>> +				 (nr_to_write - nr_written) * ZSWAP_PROACTIVE_WB_SCAN_RATIO);
>> +
>> +		while (nr_scanned < nr_to_scan) {
>> +			unsigned long nr_to_walk = min(ZSWAP_PROACTIVE_WB_BATCH,
>> +						       nr_to_scan - nr_scanned);
>> +
>> +			if (signal_pending(current))
>> +				return nr_written;
>> +
>> +			/*
>> +			 * Account for the committed budget rather than the walker's
>> +			 * actual delta. If the list is emptied concurrently, the
>> +			 * walker visits nothing and nr_scanned would never advance.
>> +			 */
>> +			nr_scanned += nr_to_walk;
>> +
>> +			nr_written += list_lru_walk_one(&zswap_list_lru, nid, memcg,
>> +							&shrink_memcg_cb,
>> +							&encountered_page_in_swapcache,
>> +							&nr_to_walk);
>> +
>> +			if (nr_written >= nr_to_write)
>> +				return nr_written;
>> +			if (encountered_page_in_swapcache)
>> +				break;
>> +
>> +			cond_resched();
>> +		}
>> +	}
>> +
>> +	return nr_written;
>> +}
>> +
>> +int zswap_proactive_writeback(struct mem_cgroup *memcg,
>> +			      unsigned long nr_to_writeback)
>> +{
>> +	struct mem_cgroup *iter_memcg;
>> +	unsigned long nr_written = 0;
>> +	int failures = 0, attempts = 0;
>> +
>> +	if (!memcg)
>> +		return -EINVAL;
>> +	if (!nr_to_writeback)
>> +		return 0;
>> +
>> +	/*
>> +	 * Writeback will be aborted with -EAGAIN if we encounter
>> +	 * the following MAX_RECLAIM_RETRIES times:
>> +	 * - No writeback-candidate memcgs found in a subtree walk.
>> +	 * - A writeback-candidate memcg wrote back zero pages.
>> +	 */
>> +	while (nr_written < nr_to_writeback) {
>> +		unsigned long batch_size;
>> +		long shrunk;
>> +
>> +		if (signal_pending(current))
>> +			return -EINTR;
>> +
>> +		iter_memcg = zswap_mem_cgroup_iter(memcg);
>> +
>> +		if (!iter_memcg) {
>> +			/*
>> +			 * Continue without incrementing failures if we found
>> +			 * candidate memcgs in the last subtree walk.
>> +			 */
>> +			if (!attempts && ++failures == MAX_RECLAIM_RETRIES)
>> +				return -EAGAIN;
>> +			attempts = 0;
>> +			continue;
>> +		}
>> +
>> +		batch_size = min(nr_to_writeback - nr_written,
>> +				 ZSWAP_PROACTIVE_WB_BATCH);
>> +		shrunk = zswap_proactive_shrink_memcg(iter_memcg, batch_size);
>> +		mem_cgroup_put(iter_memcg);
>> +
>> +		/* Writeback-disabled or offline: skip without counting. */
>> +		if (shrunk == -ENOENT)
>> +			continue;
>> +
>> +		++attempts;
>> +		if (shrunk > 0)
>> +			nr_written += shrunk;
>> +		else if (++failures == MAX_RECLAIM_RETRIES)
>> +			return -EAGAIN;
>> +
>> +		cond_resched();
>> +	}
>> +
>> +	return 0;
>> +}
>> +
> 
> There is a lot of copy+paste from shrink_worker() and shrink_memcg()
> here. We really should be able to reuse shrink_memcg().
> 

I will do some consolidation and code reuse in the next version.

> Is the main difference that we are scanning in batches here? I think we
> can have shrink_memcg() do that too. If anything, it might make the
> shrinker more efficient. Over-reclaim is ofc a concern, and especially
> in the zswap_store() path as the overhead can be noticeable. Maybe we
> can parameterize the batch size based on the code path.
> 
> Nhat, what do you think?

Nhat, since we now have the referenced-based second chance algorithm, 
should we consider doing batch writeback for shrink_memcg() as well?

Of course, we could pass a parameter to control whether batch writeback 
is needed, so as to preserve the original behavior of shrink_memcg().

Thanks,
Hao

^ permalink raw reply

* Re: [PATCH v3 2/4] mm/zswap: Implement proactive writeback
From: Hao Jia @ 2026-06-03 11:22 UTC (permalink / raw)
  To: Yosry Ahmed, Nhat Pham
  Cc: akpm, tj, hannes, shakeel.butt, mhocko, mkoutny, chengming.zhou,
	muchun.song, roman.gushchin, cgroups, linux-mm, linux-kernel,
	linux-doc, Hao Jia
In-Reply-To: <aho_VtLCmIRsNyvO@google.com>



On 2026/5/30 09:40, Yosry Ahmed wrote:
> On Fri, May 29, 2026 at 12:58:09PM -0700, Nhat Pham wrote:
>> On Tue, May 26, 2026 at 4:46 AM Hao Jia <jiahao.kernel@gmail.com> wrote:
>>>
>>> From: Hao Jia <jiahao1@lixiang.com>
>>>
>>> Zswap currently writes back pages to backing swap reactively, triggered
>>> either by the shrinker or when the pool reaches its size limit. There is
>>> no mechanism to control the amount of writeback for a specific memory
>>> cgroup. However, users may want to proactively write back zswap pages,
>>> e.g., to free up memory for other applications or to prepare for
>>> memory-intensive workloads.
>>>
>>> Introduce a "zswap_writeback_only" key to the memory.reclaim cgroup
>>> interface. When specified, this key bypasses standard memory reclaim
>>> and exclusively performs proactive zswap writeback up to the requested
>>> budget. If omitted, the default reclaim behavior remains unchanged.
>>>
>>> Example usage:
>>>    # Write back 100MB of pages from zswap to the backing swap
>>>    echo "100M zswap_writeback_only" > memory.reclaim
>>
>> Hmmm, so this 100MB is the pre-compression size? i.e if this 100 MB
>> compresses to 25 MB, then you're only freeing 25 MB?
>>
>> I'm ok-ish with this, but can you document it?
> 
> That's a good point. I think pre-compressed size doesn't make sense to
> be honest. We should care about how much memory we are actually trying
> to save by doing writeback here.
> 
> The pre-compressed size is only useful in determining the blast radius,
> how many actual pages are going to have slower page faults now. But
> then, I don't think there's a reasonable way for userspace to decide
> that.
> 
> I understand passing in the compressed size is tricky because we need to
> keep track of the size of the compressed pages we end up writing back,
> but it should be doable.

Agreed. Using pre-compressed size is probably easier to implement. IIRC, 
interfaces like ZRAM writeback_limit are also calculated using the 
pre-compressed size.

I'll clarify this in the documentation in the next version.

> 
> If we really want pre-compressed size here, then yes we need to make it
> very clear, and I vote that we use a separate interface in this case
> because memory.reclaim having different meanings for the amount of
> memory written to it is extremely counter-intuitive.
> 
Agree. This would indeed break the semantics of memory.reclaim. I will 
use a separate interface for proactive writeback in the next version.

Thanks,
Hao
>>
>> The rest seems solid to me, FWIW. I'll defer to Johannes and Yosry for
>> opinions on zswap-only proactive reclaim.

^ permalink raw reply

* Re: [PATCH] cgroup/cpuset: Support multiple source/destination cpusets using pids pattern
From: Ridong Chen @ 2026-06-03 10:32 UTC (permalink / raw)
  To: Waiman Long; +Cc: cgroups, Tejun Heo, Johannes Weiner, linux-kernel
In-Reply-To: <20260603102604.177503-1-ridong.chen@linux.dev>

Hi Longman,

I used AI to generate a patch that fixes this issue, following the same
approach as the pids subsystem. I think this may be much simpler. Just a
heads-up — this patch is only for discussion and hasn't been tested.

On 2026/6/3 18:26, Ridong Chen wrote:
> The current cpuset_can_attach() and cpuset_attach() functions assume task
> migration is from one source cpuset to one destination cpuset. This can be
> wrong in several scenarios:
>  - Moving a multi-threaded process with threads in different cpusets
>  - Disabling the cpuset controller (many children to one parent)
>  - Enabling the cpuset controller (one parent to many children)
> 
> Fix this by adopting the pids subsystem's per-task accounting pattern.
> In cpuset_can_attach(), use task_cs(task) to get the correct source cpuset
> for each task (like pids_can_attach uses task_css), adjust nr_deadline_tasks
> and reserve DL bandwidth per-task, and increment attach_in_progress per-task
> on the destination cpuset. In cpuset_attach(), handle destination cpuset
> changes within the task iteration loop.
> 
> A shared helper cpuset_undo_attach() reverses the per-task operations for
> both partial rollback in cpuset_can_attach() and full reversal in
> cpuset_cancel_attach().
> 
> When multiple source cpusets are detected in can_attach(), set
> attach_many_sources so that cpuset_attach() forces cpus_updated and
> mems_updated to true, ensuring all tasks get properly updated regardless
> of which source cpuset cpuset_attach_old_cs points to.
> 
> This eliminates the need for nr_migrate_dl_tasks, sum_migrate_dl_bw, and
> dl_bw_cpu fields in struct cpuset.
> 
> Fixes: 4ec22e9c5a90 ("cpuset: Enable cpuset controller in default hierarchy")
> Signed-off-by: Ridong Chen <ridong.chen@linux.dev>
> ---
>  kernel/cgroup/cpuset-internal.h |   8 --
>  kernel/cgroup/cpuset.c          | 177 ++++++++++++++++----------------
>  2 files changed, 89 insertions(+), 96 deletions(-)
> 
> diff --git a/kernel/cgroup/cpuset-internal.h b/kernel/cgroup/cpuset-internal.h
> index f7aaf01f7cd5..601e38b3c75b 100644
> --- a/kernel/cgroup/cpuset-internal.h
> +++ b/kernel/cgroup/cpuset-internal.h
> @@ -166,14 +166,6 @@ struct cpuset {
>  	 * know when to rebuild associated root domain bandwidth information.
>  	 */
>  	int nr_deadline_tasks;
> -	int nr_migrate_dl_tasks;
> -	/* DL bandwidth that needs destination reservation for this attach. */
> -	u64 sum_migrate_dl_bw;
> -	/*
> -	 * CPU used for temporary DL bandwidth allocation during attach;
> -	 * -1 if no DL bandwidth was allocated in the current attach.
> -	 */
> -	int dl_bw_cpu;
>  
>  	/* Invalid partition error code, not lock protected */
>  	enum prs_errcode prs_err;
> diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
> index e52a5a40d607..be222eb6078c 100644
> --- a/kernel/cgroup/cpuset.c
> +++ b/kernel/cgroup/cpuset.c
> @@ -288,7 +288,6 @@ struct cpuset top_cpuset = {
>  	.flags = BIT(CS_CPU_EXCLUSIVE) |
>  		 BIT(CS_MEM_EXCLUSIVE) | BIT(CS_SCHED_LOAD_BALANCE),
>  	.partition_root_state = PRS_ROOT,
> -	.dl_bw_cpu = -1,
>  };
>  
>  /**
> @@ -580,8 +579,6 @@ static struct cpuset *dup_or_alloc_cpuset(struct cpuset *cs)
>  	if (!trial)
>  		return NULL;
>  
> -	trial->dl_bw_cpu = -1;
> -
>  	/* Setup cpumask pointer array */
>  	cpumask_var_t *pmask[4] = {
>  		&trial->cpus_allowed,
> @@ -2984,6 +2981,7 @@ static int update_prstate(struct cpuset *cs, int new_prs)
>  static struct cpuset *cpuset_attach_old_cs;
>  static bool attach_cpus_updated;
>  static bool attach_mems_updated;
> +static bool attach_many_sources;
>  
>  /*
>   * Check to see if a cpuset can accept a new task
> @@ -3026,30 +3024,36 @@ static int cpuset_can_attach_check(struct cpuset *cs, struct cpuset *oldcs,
>  	return 0;
>  }
>  
> -static int cpuset_reserve_dl_bw(struct cpuset *cs)
> +/*
> + * Reverse per-task operations done in cpuset_can_attach().
> + * If @stop_at is non-NULL, only undo tasks before it (partial rollback).
> + * If @stop_at is NULL, undo all tasks (full reversal for cancel_attach).
> + * Must be called with cpuset_mutex held.
> + */
> +static void cpuset_undo_attach(struct cgroup_taskset *tset,
> +			       struct task_struct *stop_at)
>  {
> -	int cpu, ret;
> -
> -	if (!cs->sum_migrate_dl_bw)
> -		return 0;
> -
> -	cpu = cpumask_any_and(cpu_active_mask, cs->effective_cpus);
> -	if (unlikely(cpu >= nr_cpu_ids))
> -		return -EINVAL;
> +	struct cgroup_subsys_state *css;
> +	struct task_struct *task;
>  
> -	ret = dl_bw_alloc(cpu, cs->sum_migrate_dl_bw);
> -	if (ret)
> -		return ret;
> +	cgroup_taskset_for_each(task, css, tset) {
> +		struct cpuset *cs = css_cs(css);
> +		struct cpuset *oldcs = task_cs(task);
>  
> -	cs->dl_bw_cpu = cpu;
> -	return 0;
> -}
> +		if (task == stop_at)
> +			break;
>  
> -static void reset_migrate_dl_data(struct cpuset *cs)
> -{
> -	cs->nr_migrate_dl_tasks = 0;
> -	cs->sum_migrate_dl_bw = 0;
> -	cs->dl_bw_cpu = -1;
> +		if (dl_task(task)) {
> +			cs->nr_deadline_tasks--;
> +			oldcs->nr_deadline_tasks++;
> +			if (dl_task_needs_bw_move(task, cs->effective_cpus)) {
> +				int cpu = cpumask_any_and(cpu_active_mask,
> +							 cs->effective_cpus);
> +				dl_bw_free(cpu, task->dl.dl_bw);
> +			}
> +		}
> +		dec_attach_in_progress_locked(cs);
> +	}
>  }
>  
>  /* Called by cgroups to determine if a cpuset is usable; cpuset_mutex held */
> @@ -3061,96 +3065,79 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
>  	bool setsched_check;
>  	int ret;
>  
> -	/* used later by cpuset_attach() */
>  	cpuset_attach_old_cs = task_cs(cgroup_taskset_first(tset, &css));
>  	oldcs = cpuset_attach_old_cs;
>  	cs = css_cs(css);
>  
>  	mutex_lock(&cpuset_mutex);
> +	attach_many_sources = false;
>  
> -	/* Check to see if task is allowed in the cpuset */
>  	ret = cpuset_can_attach_check(cs, oldcs, &setsched_check);
>  	if (ret)
>  		goto out_unlock;
>  
> -	/*
> -	 * The cpuset_attach_old_cs is used mainly by cpuset_migrate_mm() to get
> -	 * the old_mems_allowed value. There are two ways that many-to-one
> -	 * cpuset migration can happen:
> -	 * 1) A multithread application with threads in different cpusets is
> -	 *    wholely migrated to a new cpuset.
> -	 * 2) Disabling v2 cpuset controller will move all the tasks in child
> -	 *    cpusets to the parent cpuset.
> -	 *
> -	 * In the former case, it is the mm setting of the group leader that
> -	 * really matters. So cpuset_attach_old_cs should track the oldcs of the
> -	 * group leader. It falls back to the oldcs of the first task if there
> -	 * is no group leader in the taskset. In the latter case, effective_mems
> -	 * of child cpusets must always be a subset of the parent. So no real
> -	 * page migration will be necessary no matter which child cpuset is
> -	 * selected as cpuset_attach_old_cs.
> -	 */
>  	cgroup_taskset_for_each(task, css, tset) {
> +		struct cpuset *newcs = css_cs(css);
> +		struct cpuset *new_oldcs = task_cs(task);
> +
> +		if (newcs != cs || new_oldcs != oldcs) {
> +			if (new_oldcs != oldcs)
> +				attach_many_sources = true;
> +			cs = newcs;
> +			oldcs = new_oldcs;
> +			ret = cpuset_can_attach_check(cs, oldcs,
> +						      &setsched_check);
> +			if (ret)
> +				goto out_rollback;
> +		}
> +
>  		ret = task_can_attach(task);
>  		if (ret)
> -			goto out_unlock;
> +			goto out_rollback;
>  
> -		/* Update cpuset_attach_old_cs to the latest group leader */
>  		if (task == task->group_leader)
>  			cpuset_attach_old_cs = task_cs(task);
>  
>  		if (setsched_check) {
>  			ret = security_task_setscheduler(task);
>  			if (ret)
> -				goto out_unlock;
> +				goto out_rollback;
>  		}
>  
>  		if (dl_task(task)) {
> -			/*
> -			 * Count all migrating DL tasks for cpuset task accounting.
> -			 * Only tasks that need a root-domain bandwidth move
> -			 * contribute to sum_migrate_dl_bw.
> -			 */
> -			cs->nr_migrate_dl_tasks++;
> -			if (dl_task_needs_bw_move(task, cs->effective_cpus))
> -				cs->sum_migrate_dl_bw += task->dl.dl_bw;
> +			cs->nr_deadline_tasks++;
> +			oldcs->nr_deadline_tasks--;
> +
> +			if (dl_task_needs_bw_move(task, cs->effective_cpus)) {
> +				int cpu = cpumask_any_and(cpu_active_mask,
> +							 cs->effective_cpus);
> +				if (unlikely(cpu >= nr_cpu_ids)) {
> +					ret = -EINVAL;
> +					goto out_rollback;
> +				}
> +				ret = dl_bw_alloc(cpu, task->dl.dl_bw);
> +				if (ret)
> +					goto out_rollback;
> +			}
>  		}
> -	}
> -
> -	ret = cpuset_reserve_dl_bw(cs);
>  
> -out_unlock:
> -	if (ret) {
> -		reset_migrate_dl_data(cs);
> -	} else {
> -		/*
> -		 * Mark attach is in progress.  This makes validate_change() fail
> -		 * changes which zero cpus/mems_allowed.
> -		 */
>  		cs->attach_in_progress++;
>  	}
>  
> +	goto out_unlock;
> +
> +out_rollback:
> +	cpuset_undo_attach(tset, task);
> +
> +out_unlock:
>  	mutex_unlock(&cpuset_mutex);
>  	return ret;
>  }
>  
>  static void cpuset_cancel_attach(struct cgroup_taskset *tset)
>  {
> -	struct cgroup_subsys_state *css;
> -	struct cpuset *cs;
> -
> -	cgroup_taskset_first(tset, &css);
> -	cs = css_cs(css);
> -
>  	mutex_lock(&cpuset_mutex);
> -	dec_attach_in_progress_locked(cs);
> -
> -	if (cs->dl_bw_cpu >= 0)
> -		dl_bw_free(cs->dl_bw_cpu, cs->sum_migrate_dl_bw);
> -
> -	if (cs->nr_migrate_dl_tasks)
> -		reset_migrate_dl_data(cs);
> -
> +	cpuset_undo_attach(tset, NULL);
>  	mutex_unlock(&cpuset_mutex);
>  }
>  
> @@ -3232,8 +3219,15 @@ static void cpuset_attach(struct cgroup_taskset *tset)
>  	mutex_lock(&cpuset_mutex);
>  	queue_task_work = false;
>  
> -	attach_cpus_updated = !cpumask_equal(cs->effective_cpus, oldcs->effective_cpus);
> -	attach_mems_updated = !nodes_equal(cs->effective_mems, oldcs->effective_mems);
> +	if (attach_many_sources) {
> +		attach_cpus_updated = true;
> +		attach_mems_updated = true;
> +	} else {
> +		attach_cpus_updated = !cpumask_equal(cs->effective_cpus,
> +						     oldcs->effective_cpus);
> +		attach_mems_updated = !nodes_equal(cs->effective_mems,
> +						    oldcs->effective_mems);
> +	}
>  
>  	/*
>  	 * In the default hierarchy, enabling cpuset in the child cgroups
> @@ -3249,21 +3243,28 @@ static void cpuset_attach(struct cgroup_taskset *tset)
>  		guarantee_online_mems(cs, &cpuset_attach_nodemask_to);
>  	}
>  
> -	cgroup_taskset_for_each(task, css, tset)
> +	cgroup_taskset_for_each(task, css, tset) {
> +		struct cpuset *newcs = css_cs(css);
> +
> +		if (newcs != cs) {
> +			cs->old_mems_allowed = cpuset_attach_nodemask_to;
> +			cs = newcs;
> +			if (cpuset_v2())
> +				cpuset_attach_nodemask_to = cs->effective_mems;
> +			else
> +				guarantee_online_mems(cs, &cpuset_attach_nodemask_to);
> +		}
>  		cpuset_attach_task(cs, task);
> +	}
>  
>  out:
>  	if (queue_task_work)
>  		schedule_flush_migrate_mm();
>  	cs->old_mems_allowed = cpuset_attach_nodemask_to;
>  
> -	if (cs->nr_migrate_dl_tasks) {
> -		cs->nr_deadline_tasks += cs->nr_migrate_dl_tasks;
> -		oldcs->nr_deadline_tasks -= cs->nr_migrate_dl_tasks;
> -		reset_migrate_dl_data(cs);
> -	}
> -
> -	dec_attach_in_progress_locked(cs);
> +	/* Decrement per-task attach_in_progress */
> +	cgroup_taskset_for_each(task, css, tset)
> +		dec_attach_in_progress_locked(css_cs(css));
>  
>  	mutex_unlock(&cpuset_mutex);
>  }

-- 
Best regards,
Ridong

^ permalink raw reply

* [PATCH] cgroup/cpuset: Support multiple source/destination cpusets using pids pattern
From: Ridong Chen @ 2026-06-03 10:26 UTC (permalink / raw)
  To: Waiman Long
  Cc: cgroups, Tejun Heo, Johannes Weiner, ridong.chen, linux-kernel
In-Reply-To: <20260602023203.248077-7-longman@redhat.com>

The current cpuset_can_attach() and cpuset_attach() functions assume task
migration is from one source cpuset to one destination cpuset. This can be
wrong in several scenarios:
 - Moving a multi-threaded process with threads in different cpusets
 - Disabling the cpuset controller (many children to one parent)
 - Enabling the cpuset controller (one parent to many children)

Fix this by adopting the pids subsystem's per-task accounting pattern.
In cpuset_can_attach(), use task_cs(task) to get the correct source cpuset
for each task (like pids_can_attach uses task_css), adjust nr_deadline_tasks
and reserve DL bandwidth per-task, and increment attach_in_progress per-task
on the destination cpuset. In cpuset_attach(), handle destination cpuset
changes within the task iteration loop.

A shared helper cpuset_undo_attach() reverses the per-task operations for
both partial rollback in cpuset_can_attach() and full reversal in
cpuset_cancel_attach().

When multiple source cpusets are detected in can_attach(), set
attach_many_sources so that cpuset_attach() forces cpus_updated and
mems_updated to true, ensuring all tasks get properly updated regardless
of which source cpuset cpuset_attach_old_cs points to.

This eliminates the need for nr_migrate_dl_tasks, sum_migrate_dl_bw, and
dl_bw_cpu fields in struct cpuset.

Fixes: 4ec22e9c5a90 ("cpuset: Enable cpuset controller in default hierarchy")
Signed-off-by: Ridong Chen <ridong.chen@linux.dev>
---
 kernel/cgroup/cpuset-internal.h |   8 --
 kernel/cgroup/cpuset.c          | 177 ++++++++++++++++----------------
 2 files changed, 89 insertions(+), 96 deletions(-)

diff --git a/kernel/cgroup/cpuset-internal.h b/kernel/cgroup/cpuset-internal.h
index f7aaf01f7cd5..601e38b3c75b 100644
--- a/kernel/cgroup/cpuset-internal.h
+++ b/kernel/cgroup/cpuset-internal.h
@@ -166,14 +166,6 @@ struct cpuset {
 	 * know when to rebuild associated root domain bandwidth information.
 	 */
 	int nr_deadline_tasks;
-	int nr_migrate_dl_tasks;
-	/* DL bandwidth that needs destination reservation for this attach. */
-	u64 sum_migrate_dl_bw;
-	/*
-	 * CPU used for temporary DL bandwidth allocation during attach;
-	 * -1 if no DL bandwidth was allocated in the current attach.
-	 */
-	int dl_bw_cpu;
 
 	/* Invalid partition error code, not lock protected */
 	enum prs_errcode prs_err;
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index e52a5a40d607..be222eb6078c 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -288,7 +288,6 @@ struct cpuset top_cpuset = {
 	.flags = BIT(CS_CPU_EXCLUSIVE) |
 		 BIT(CS_MEM_EXCLUSIVE) | BIT(CS_SCHED_LOAD_BALANCE),
 	.partition_root_state = PRS_ROOT,
-	.dl_bw_cpu = -1,
 };
 
 /**
@@ -580,8 +579,6 @@ static struct cpuset *dup_or_alloc_cpuset(struct cpuset *cs)
 	if (!trial)
 		return NULL;
 
-	trial->dl_bw_cpu = -1;
-
 	/* Setup cpumask pointer array */
 	cpumask_var_t *pmask[4] = {
 		&trial->cpus_allowed,
@@ -2984,6 +2981,7 @@ static int update_prstate(struct cpuset *cs, int new_prs)
 static struct cpuset *cpuset_attach_old_cs;
 static bool attach_cpus_updated;
 static bool attach_mems_updated;
+static bool attach_many_sources;
 
 /*
  * Check to see if a cpuset can accept a new task
@@ -3026,30 +3024,36 @@ static int cpuset_can_attach_check(struct cpuset *cs, struct cpuset *oldcs,
 	return 0;
 }
 
-static int cpuset_reserve_dl_bw(struct cpuset *cs)
+/*
+ * Reverse per-task operations done in cpuset_can_attach().
+ * If @stop_at is non-NULL, only undo tasks before it (partial rollback).
+ * If @stop_at is NULL, undo all tasks (full reversal for cancel_attach).
+ * Must be called with cpuset_mutex held.
+ */
+static void cpuset_undo_attach(struct cgroup_taskset *tset,
+			       struct task_struct *stop_at)
 {
-	int cpu, ret;
-
-	if (!cs->sum_migrate_dl_bw)
-		return 0;
-
-	cpu = cpumask_any_and(cpu_active_mask, cs->effective_cpus);
-	if (unlikely(cpu >= nr_cpu_ids))
-		return -EINVAL;
+	struct cgroup_subsys_state *css;
+	struct task_struct *task;
 
-	ret = dl_bw_alloc(cpu, cs->sum_migrate_dl_bw);
-	if (ret)
-		return ret;
+	cgroup_taskset_for_each(task, css, tset) {
+		struct cpuset *cs = css_cs(css);
+		struct cpuset *oldcs = task_cs(task);
 
-	cs->dl_bw_cpu = cpu;
-	return 0;
-}
+		if (task == stop_at)
+			break;
 
-static void reset_migrate_dl_data(struct cpuset *cs)
-{
-	cs->nr_migrate_dl_tasks = 0;
-	cs->sum_migrate_dl_bw = 0;
-	cs->dl_bw_cpu = -1;
+		if (dl_task(task)) {
+			cs->nr_deadline_tasks--;
+			oldcs->nr_deadline_tasks++;
+			if (dl_task_needs_bw_move(task, cs->effective_cpus)) {
+				int cpu = cpumask_any_and(cpu_active_mask,
+							 cs->effective_cpus);
+				dl_bw_free(cpu, task->dl.dl_bw);
+			}
+		}
+		dec_attach_in_progress_locked(cs);
+	}
 }
 
 /* Called by cgroups to determine if a cpuset is usable; cpuset_mutex held */
@@ -3061,96 +3065,79 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
 	bool setsched_check;
 	int ret;
 
-	/* used later by cpuset_attach() */
 	cpuset_attach_old_cs = task_cs(cgroup_taskset_first(tset, &css));
 	oldcs = cpuset_attach_old_cs;
 	cs = css_cs(css);
 
 	mutex_lock(&cpuset_mutex);
+	attach_many_sources = false;
 
-	/* Check to see if task is allowed in the cpuset */
 	ret = cpuset_can_attach_check(cs, oldcs, &setsched_check);
 	if (ret)
 		goto out_unlock;
 
-	/*
-	 * The cpuset_attach_old_cs is used mainly by cpuset_migrate_mm() to get
-	 * the old_mems_allowed value. There are two ways that many-to-one
-	 * cpuset migration can happen:
-	 * 1) A multithread application with threads in different cpusets is
-	 *    wholely migrated to a new cpuset.
-	 * 2) Disabling v2 cpuset controller will move all the tasks in child
-	 *    cpusets to the parent cpuset.
-	 *
-	 * In the former case, it is the mm setting of the group leader that
-	 * really matters. So cpuset_attach_old_cs should track the oldcs of the
-	 * group leader. It falls back to the oldcs of the first task if there
-	 * is no group leader in the taskset. In the latter case, effective_mems
-	 * of child cpusets must always be a subset of the parent. So no real
-	 * page migration will be necessary no matter which child cpuset is
-	 * selected as cpuset_attach_old_cs.
-	 */
 	cgroup_taskset_for_each(task, css, tset) {
+		struct cpuset *newcs = css_cs(css);
+		struct cpuset *new_oldcs = task_cs(task);
+
+		if (newcs != cs || new_oldcs != oldcs) {
+			if (new_oldcs != oldcs)
+				attach_many_sources = true;
+			cs = newcs;
+			oldcs = new_oldcs;
+			ret = cpuset_can_attach_check(cs, oldcs,
+						      &setsched_check);
+			if (ret)
+				goto out_rollback;
+		}
+
 		ret = task_can_attach(task);
 		if (ret)
-			goto out_unlock;
+			goto out_rollback;
 
-		/* Update cpuset_attach_old_cs to the latest group leader */
 		if (task == task->group_leader)
 			cpuset_attach_old_cs = task_cs(task);
 
 		if (setsched_check) {
 			ret = security_task_setscheduler(task);
 			if (ret)
-				goto out_unlock;
+				goto out_rollback;
 		}
 
 		if (dl_task(task)) {
-			/*
-			 * Count all migrating DL tasks for cpuset task accounting.
-			 * Only tasks that need a root-domain bandwidth move
-			 * contribute to sum_migrate_dl_bw.
-			 */
-			cs->nr_migrate_dl_tasks++;
-			if (dl_task_needs_bw_move(task, cs->effective_cpus))
-				cs->sum_migrate_dl_bw += task->dl.dl_bw;
+			cs->nr_deadline_tasks++;
+			oldcs->nr_deadline_tasks--;
+
+			if (dl_task_needs_bw_move(task, cs->effective_cpus)) {
+				int cpu = cpumask_any_and(cpu_active_mask,
+							 cs->effective_cpus);
+				if (unlikely(cpu >= nr_cpu_ids)) {
+					ret = -EINVAL;
+					goto out_rollback;
+				}
+				ret = dl_bw_alloc(cpu, task->dl.dl_bw);
+				if (ret)
+					goto out_rollback;
+			}
 		}
-	}
-
-	ret = cpuset_reserve_dl_bw(cs);
 
-out_unlock:
-	if (ret) {
-		reset_migrate_dl_data(cs);
-	} else {
-		/*
-		 * Mark attach is in progress.  This makes validate_change() fail
-		 * changes which zero cpus/mems_allowed.
-		 */
 		cs->attach_in_progress++;
 	}
 
+	goto out_unlock;
+
+out_rollback:
+	cpuset_undo_attach(tset, task);
+
+out_unlock:
 	mutex_unlock(&cpuset_mutex);
 	return ret;
 }
 
 static void cpuset_cancel_attach(struct cgroup_taskset *tset)
 {
-	struct cgroup_subsys_state *css;
-	struct cpuset *cs;
-
-	cgroup_taskset_first(tset, &css);
-	cs = css_cs(css);
-
 	mutex_lock(&cpuset_mutex);
-	dec_attach_in_progress_locked(cs);
-
-	if (cs->dl_bw_cpu >= 0)
-		dl_bw_free(cs->dl_bw_cpu, cs->sum_migrate_dl_bw);
-
-	if (cs->nr_migrate_dl_tasks)
-		reset_migrate_dl_data(cs);
-
+	cpuset_undo_attach(tset, NULL);
 	mutex_unlock(&cpuset_mutex);
 }
 
@@ -3232,8 +3219,15 @@ static void cpuset_attach(struct cgroup_taskset *tset)
 	mutex_lock(&cpuset_mutex);
 	queue_task_work = false;
 
-	attach_cpus_updated = !cpumask_equal(cs->effective_cpus, oldcs->effective_cpus);
-	attach_mems_updated = !nodes_equal(cs->effective_mems, oldcs->effective_mems);
+	if (attach_many_sources) {
+		attach_cpus_updated = true;
+		attach_mems_updated = true;
+	} else {
+		attach_cpus_updated = !cpumask_equal(cs->effective_cpus,
+						     oldcs->effective_cpus);
+		attach_mems_updated = !nodes_equal(cs->effective_mems,
+						    oldcs->effective_mems);
+	}
 
 	/*
 	 * In the default hierarchy, enabling cpuset in the child cgroups
@@ -3249,21 +3243,28 @@ static void cpuset_attach(struct cgroup_taskset *tset)
 		guarantee_online_mems(cs, &cpuset_attach_nodemask_to);
 	}
 
-	cgroup_taskset_for_each(task, css, tset)
+	cgroup_taskset_for_each(task, css, tset) {
+		struct cpuset *newcs = css_cs(css);
+
+		if (newcs != cs) {
+			cs->old_mems_allowed = cpuset_attach_nodemask_to;
+			cs = newcs;
+			if (cpuset_v2())
+				cpuset_attach_nodemask_to = cs->effective_mems;
+			else
+				guarantee_online_mems(cs, &cpuset_attach_nodemask_to);
+		}
 		cpuset_attach_task(cs, task);
+	}
 
 out:
 	if (queue_task_work)
 		schedule_flush_migrate_mm();
 	cs->old_mems_allowed = cpuset_attach_nodemask_to;
 
-	if (cs->nr_migrate_dl_tasks) {
-		cs->nr_deadline_tasks += cs->nr_migrate_dl_tasks;
-		oldcs->nr_deadline_tasks -= cs->nr_migrate_dl_tasks;
-		reset_migrate_dl_data(cs);
-	}
-
-	dec_attach_in_progress_locked(cs);
+	/* Decrement per-task attach_in_progress */
+	cgroup_taskset_for_each(task, css, tset)
+		dec_attach_in_progress_locked(css_cs(css));
 
 	mutex_unlock(&cpuset_mutex);
 }
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH cgroup/for-next v2 0/5] cgroup/cpuset: Support multiple source/destination cpusets for cpuset_*attach()
From: Ridong Chen @ 2026-06-03 10:05 UTC (permalink / raw)
  To: Waiman Long, Chen Ridong, Tejun Heo, Johannes Weiner,
	Michal Koutný, Ingo Molnar, Peter Zijlstra, Juri Lelli,
	Vincent Guittot, Dietmar Eggemann, Steven Rostedt, Ben Segall,
	Mel Gorman, Valentin Schneider, K Prateek Nayak
  Cc: cgroups, linux-kernel, Aaron Tomlin
In-Reply-To: <b91080da-486c-4df0-9e6b-8eb3364cae45@redhat.com>



On 2026/5/27 4:12, Waiman Long wrote:
> 
> On 5/20/26 4:29 AM, Ridong Chen wrote:
>>
>>
>> On 2026/5/16 12:24, Waiman Long wrote:
>>> Sashiko AI review of another cpuset patch had found that cpuset_attach()
>>> and cpuset_can_attach() can be passed a cgroup_taskset with tasks
>>> migrating from one source cpuset to multiple destination cpusets and
>>> vice versa.  Further testing of the cpuset code indicates that this is
>>> indeed the case when the v2 cpuset controller is enabled or disabled.
>>>
>>> Unfortunately, cpuset_attach() and cpuset_can_attach() still assume that
>>> there will be one source and one destinaton cpuset which may result in
>>> inocrrect behavior.
>>>
>>
>> Hi Longman,
>>
>> I am thinking whether we can use the pids subsystem's approach to
>> solve this issue, which I think could be much simpler.
>>
>> For the DL task accounting, we can handle it the same way
>> pids_can_attach() does - just call task_cs(task) for each task
>> individually inside the can_attach() loop and do the nr_deadline_tasks
>> adjustment right there. This eliminates the need to pass per-task
>> source cpuset information to the attach() callback entirely for DL
>> accounting purposes.
> DL task accounting doesn't use the new oldcs stored in the task
> structure which is only used for mm migration. BTW, I believe
> task_cs(task) doesn't return the old cs in cpuset_attach().

Sorry for the late response.

If I understand correctly, for DL task accounting, we need to know the
destination cpuset to allocate bandwidth. The destination cpuset can be
obtained in cpuset_can_attach.

You are right that task_cs(task) does not return the old cpuset in
cpuset_attach(). But do we really need the old cpuset in cpuset_attach?
Is cpuset_attach_old_cs sufficient for mm migration?

>>
>> For cpuset_migrate_mm(), I don't think we need per-task oldcs storage
>> in task_struct either. The scenarios where multiple source cpusets are
>> involved are:
>>
>> enable cpuset controller: child cpusets inherit parent's
>> effective_mems, so attach_mems_updated is false and
>> cpuset_migrate_mm() is never called.
>>
>> disable cpuset controller: tasks move from children to parent. Since
>> children's effective_mems is always a subset of parent's
>> effective_mems, even if cpuset_migrate_mm() is triggered, it's
>> effectively a noop (no pages need to move from a subset to its superset).
>>
>> cgroup.procs write with threads in different cpusets: this is a
>> many-to-one migration with a single process, so there is only one
>> group_leader and one mm. We only need to record the leader's oldcs,
>> which a single static variable can handle.
>>
>> So in all cases, the migration path only needs one oldcs for the
>> leader. We don't need to add a field to task_struct.
>>
>> What do you think?
> 
> Yes, that makes sense. I will rework the patch series.
> 
> Thanks,
> Longman
> 
>>
>>
>>
>>> This patch series is created to fix this issue. The first 2 patches are
>>> just preparatory patches to make the remaining patches easier to review.
>>>
>>> Patch 3 adds a new attach_old_cs field into task_struct to track the
>>> old cpuset to be used in case when cpuset_migrate_mm() needs to be
>>> called in cpuset_attach().
>>>
>>> Patch 4 moves mpol_rebind_mm() and cpuset_migrate_mm() inside
>>> cpuset_attach_task() to make CLONE_INTO_CGROUP flag of clone(2) works
>>> more like moving task from one cpuset to another one, while also make
>>> supporting multiple source and destination cpusets easier.
>>>
>>> Patch 5 makes the necessary changes to enable the support of multiple
>>> source and destination cpusets by keeping all the source and destination
>>> cpusets found during task iterations in two singly linked lists for
>>> source and destination cpusets respectively.
>>>
>>> Waiman Long (5):
>>>    cgroup/cpuset: Add a cpuset_reserve_dl_bw() helper
>>>    cgroup/cpuset: Expand the scope of cpuset_can_attach_check()
>>>    cgroup/cpuset: Replace cpuset_attach_old_cs by a new attach_old_cs
>>>      field in task_struct
>>>    cgroup/cpuset: Move mpol_rebind_mm/cpuset_migrate_mm() calls inside
>>>      cpuset_attach_task()
>>>    cgroup/cpuset: Support multiple source/destination cpusets for
>>>      cpuset_*attach()
>>>
>>>   include/linux/sched.h           |   3 +
>>>   kernel/cgroup/cpuset-internal.h |   6 +
>>>   kernel/cgroup/cpuset.c          | 358 +++++++++++++++++++++-----------
>>>   3 files changed, 249 insertions(+), 118 deletions(-)
>>>
>>
> 
> 

-- 
Best regards,
Ridong

^ permalink raw reply

* Re: [PATCH v2 08/10] sched/fair: Add newidle balance to pick_task_fair()
From: Aaron Lu @ 2026-06-03  9:51 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: mingo, longman, chenridong, juri.lelli, vincent.guittot,
	dietmar.eggemann, rostedt, bsegall, mgorman, vschneid, tj, hannes,
	mkoutny, cgroups, linux-kernel, jstultz, kprateek.nayak, qyousef
In-Reply-To: <20260511120627.944705718@infradead.org>

[-- Attachment #1: Type: text/plain, Size: 2467 bytes --]

Hi Peter,

On Mon, May 11, 2026 at 01:31:12PM +0200, Peter Zijlstra wrote:
> With commit 50653216e4ff ("sched: Add support to pick functions to
> take rf") removing the balance callback, the pick_task() callback is
> in charge of newidle balancing.
> 
> This means pick_task_fair() should do so too. This hasn't been a
> problem in practise because pick_next_task_fair() is used. However,
> since we'll be removing that one shortly, make sure pick_next_task()
> is up to scratch.

While testing Prateek's throttle series, I noticed a panic issue when
coresched is enabled and bisected to this patch.

I fed the panic log and this patch to an agent and its analysis looks
correct to me(cpu56 and cpu57 are siblings in a VM):

       cpu57 (holds core-wide lock)

     pick_next_task() [core scheduling]
     for_each_cpu_wrap(i, smt_mask, 57):
       i=57: pick_task(rq_57)
             pick_task_fair(rq_57)
             -> picks task A
       rq_57->core_pick = task A
       // task_rq(A) == rq_57

       i=56: pick_task(rq_56)
             pick_task_fair(rq_56)
             cfs_rq->nr_queued == 0
             goto idle
             sched_balance_newidle(rq_56)
             raw_spin_rq_unlock(rq_56)
             // core-wide lock released
             newidle_balance() pulls
               task A: rq_57 -> rq_56
             // task_rq(A) == rq_56 now
             raw_spin_rq_lock(rq_56)
             // core-wide lock re-acquired
             return > 0
             goto again
             pick_task_fair(rq_56)
             -> picks task A
       rq_56->core_pick = task A

     // first loop done
     // rq_57->core_pick is still task A (set before lock release)
     // but task_rq(A) == rq_56 now
     next = rq_57->core_pick  // = task A

     put_prev_set_next_task(rq_57, prev, task A)
     __set_next_task_fair(rq_57, task A)
     hrtick_start_fair(rq_57, task A)
     WARN_ON_ONCE(task_rq(task A) != rq_57)
     // task_rq(A) == rq_56

I applied below diff and the problem is gone:

diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 5f48af700fd44..942a543af3e54 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -9897,6 +9897,9 @@ static struct task_struct *pick_task_fair(struct rq *rq, struct rq_flags *rf)
 	return p;
 
 idle:
+	if (sched_core_enabled(rq))
+		return NULL;
+
 	new_tasks = sched_balance_newidle(rq, rf);
 	if (new_tasks < 0)
 		return RETRY_TASK;

Full dmesg of the panic is attached for your reference.

[-- Attachment #2: dmesg_b3a2dfa8b42 --]
[-- Type: application/octet-stream, Size: 78556 bytes --]

SeaBIOS (version 1.16.2-debian-1.16.2-1)


iPXE (http://ipxe.org) 00:02.0 CA00 PCI2.10 PnP PMM+BEFCEE10+BEF0EE10 CA00



Booting from ROM..
[    0.000000] Linux version 7.1.0-rc2-00057-gb3a2dfa8b42e (ziqianlu@n232-168-014) (x86_64-linux-gcc (GCC) 12.5.0, GNU 6
[    0.000000] Command line: root=/dev/vda2 selinux=0 console=ttyS0 initcall_debug
[    0.000000] x86/split lock detection: #DB: warning on user-space bus_locks
[    0.000000] BIOS-provided physical RAM map:
[    0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff]  System RAM
[    0.000000] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff]  device reserved
[    0.000000] BIOS-e820: [gap 0x00000000000a0000-0x00000000000effff]
[    0.000000] BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff]  device reserved
[    0.000000] BIOS-e820: [mem 0x0000000000100000-0x00000000bffd6fff]  System RAM
[    0.000000] BIOS-e820: [mem 0x00000000bffd7000-0x00000000bfffffff]  device reserved
[    0.000000] BIOS-e820: [gap 0x00000000c0000000-0x00000000feffbfff]
[    0.000000] BIOS-e820: [mem 0x00000000feffc000-0x00000000feffffff]  device reserved
[    0.000000] BIOS-e820: [gap 0x00000000ff000000-0x00000000fffbffff]
[    0.000000] BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff]  device reserved
[    0.000000] BIOS-e820: [mem 0x0000000100000000-0x000000103fffffff]  System RAM
[    0.000000] NX (Execute Disable) protection: active
[    0.000000] APIC: Static calls initialized
[    0.000000] DMI: SMBIOS 2.8 present.
[    0.000000] DMI: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
[    0.000000] DMI: Memory slots populated: 4/4
[    0.000000] Hypervisor detected: KVM
[    0.000000] last_pfn = 0xbffd7 max_arch_pfn = 0x10000000000
[    0.000000] kvm-clock: Using msrs 4b564d01 and 4b564d00
[    0.000003] kvm-clock: using sched offset of 404261872 cycles
[    0.000005] clocksource: kvm-clock: mask: 0xffffffffffffffff max_cycles: 0x1cd42e4dffb, max_idle_ns: 881590591483 ns
[    0.000011] tsc: Detected 2600.000 MHz processor
[    0.001117] last_pfn = 0x1040000 max_arch_pfn = 0x10000000000
[    0.001170] MTRR map: 4 entries (3 fixed + 1 variable; max 19), built from 8 variable MTRRs
[    0.001173] x86/PAT: Configuration [0-7]: WB  WC  UC- UC  WB  WP  UC- WT
[    0.001237] last_pfn = 0xbffd7 max_arch_pfn = 0x10000000000
[    0.001244] Using GB pages for direct mapping
[    0.001787] ACPI: Early table checksum verification disabled
[    0.001790] ACPI: RSDP 0x00000000000F58F0 000014 (v00 BOCHS )
[    0.001798] ACPI: RSDT 0x00000000BFFE31DE 000034 (v01 BOCHS  BXPC     00000001 BXPC 00000001)
[    0.001803] ACPI: FACP 0x00000000BFFE2E9A 000074 (v01 BOCHS  BXPC     00000001 BXPC 00000001)
[    0.001807] ACPI: DSDT 0x00000000BFFE0040 002E5A (v01 BOCHS  BXPC     00000001 BXPC 00000001)
[    0.001810] ACPI: FACS 0x00000000BFFE0000 000040
[    0.001812] ACPI: APIC 0x00000000BFFE2F0E 000270 (v01 BOCHS  BXPC     00000001 BXPC 00000001)
[    0.001814] ACPI: HPET 0x00000000BFFE317E 000038 (v01 BOCHS  BXPC     00000001 BXPC 00000001)
[    0.001816] ACPI: WAET 0x00000000BFFE31B6 000028 (v01 BOCHS  BXPC     00000001 BXPC 00000001)
[    0.001818] ACPI: Reserving FACP table memory at [mem 0xbffe2e9a-0xbffe2f0d]
[    0.001819] ACPI: Reserving DSDT table memory at [mem 0xbffe0040-0xbffe2e99]
[    0.001820] ACPI: Reserving FACS table memory at [mem 0xbffe0000-0xbffe003f]
[    0.001821] ACPI: Reserving APIC table memory at [mem 0xbffe2f0e-0xbffe317d]
[    0.001821] ACPI: Reserving HPET table memory at [mem 0xbffe317e-0xbffe31b5]
[    0.001822] ACPI: Reserving WAET table memory at [mem 0xbffe31b6-0xbffe31dd]
[    0.001866] No NUMA configuration found
[    0.001867] Faking a node at [mem 0x0000000000000000-0x000000103fffffff]
[    0.001875] NODE_DATA(0) allocated [mem 0x103ffdb840-0x103fffdfff]
[    0.002595] ACPI: PM-Timer IO Port: 0x608
[    0.002612] ACPI: LAPIC_NMI (acpi_id[0xff] dfl dfl lint[0x1])
[    0.002663] IOAPIC[0]: apic_id 0, version 17, address 0xfec00000, GSI 0-23
[    0.002666] ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl)
[    0.002667] ACPI: INT_SRC_OVR (bus 0 bus_irq 5 global_irq 5 high level)
[    0.002669] ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 high level)
[    0.002669] ACPI: INT_SRC_OVR (bus 0 bus_irq 10 global_irq 10 high level)
[    0.002670] ACPI: INT_SRC_OVR (bus 0 bus_irq 11 global_irq 11 high level)
[    0.002674] ACPI: Using ACPI (MADT) for SMP configuration information
[    0.002675] ACPI: HPET id: 0x8086a201 base: 0xfed00000
[    0.002677] TSC deadline timer available
[    0.002679] CPU topo: Max. logical packages:   1
[    0.002680] CPU topo: Max. logical nodes:      1
[    0.002681] CPU topo: Num. nodes per package:  1
[    0.002682] CPU topo: Max. logical dies:       1
[    0.002683] CPU topo: Max. dies per package:   1
[    0.002685] CPU topo: Max. threads per core:   2
[    0.002686] CPU topo: Num. cores per package:    32
[    0.002686] CPU topo: Num. threads per package:  64
[    0.002687] CPU topo: Allowing 64 present CPUs plus 0 hotplug CPUs
[    0.002725] kvm-guest: APIC: eoi() replaced with kvm_guest_apic_eoi_write()
[    0.002739] kvm-guest: KVM setup pv remote TLB flush
[    0.002745] kvm-guest: setup PV sched yield
[    0.002758] [gap 0xc0000000-0xfeffbfff] available for PCI devices
[    0.002759] Booting paravirtualized kernel on KVM
[    0.002760] clocksource: refined-jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.158473] Zone ranges:
[    0.158475]   DMA      [mem 0x0000000000001000-0x0000000000ffffff]
[    0.158478]   DMA32    [mem 0x0000000001000000-0x00000000ffffffff]
[    0.158480]   Normal   [mem 0x0000000100000000-0x000000103fffffff]
[    0.158481] Movable zone start for each node
[    0.158483] Early memory node ranges
[    0.158483]   node   0: [mem 0x0000000000001000-0x000000000009efff]
[    0.158485]   node   0: [mem 0x0000000000100000-0x00000000bffd6fff]
[    0.158486]   node   0: [mem 0x0000000100000000-0x000000103fffffff]
[    0.158495] Initmem setup node 0 [mem 0x0000000000001000-0x000000103fffffff]
[    0.158512] On node 0, zone DMA: 1 pages in unavailable ranges
[    0.158545] On node 0, zone DMA: 97 pages in unavailable ranges
[    0.277831] On node 0, zone Normal: 41 pages in unavailable ranges
[    0.277836] setup_percpu: NR_CPUS:8192 nr_cpumask_bits:64 nr_cpu_ids:64 nr_node_ids:1
[    0.331107] percpu: Embedded 522 pages/cpu s2097176 r8192 d32744 u4194304
[    0.331229] kvm-guest: PV spinlocks enabled
[    0.331232] PV qspinlock hash table entries: 256 (order: 0, 4096 bytes, linear)
[    0.331242] Kernel command line: root=/dev/vda2 selinux=0 console=ttyS0 initcall_debug
[    0.331274] Unknown kernel command line parameters "selinux=0", will be passed to user space.
[    0.331293] random: crng init done
[    0.331294] printk: log buffer data + meta data: 16777216 + 58720256 = 75497472 bytes
[    0.340831] Dentry cache hash table entries: 8388608 (order: 14, 67108864 bytes, linear)
[    0.345633] Inode-cache hash table entries: 4194304 (order: 13, 33554432 bytes, linear)
[    0.346506] software IO TLB: area num 64.
[    0.363064] Fallback order for Node 0: 0
[    0.363076] Built 1 zonelists, mobility grouping on.  Total pages: 16777077
[    0.363077] Policy zone: Normal
[    0.363081] mem auto-init: stack:off, heap alloc:off, heap free:off
[    0.506688] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=64, Nodes=1
[    0.520070] ftrace: allocating 41111 entries in 162 pages
[    0.520071] ftrace: allocated 162 pages with 3 groups
[    0.522760] Dynamic Preempt: lazy
[    0.524044] Running RCU self tests
[    0.524045] Running RCU synchronous self tests
[    0.524046] rcu: Preemptible hierarchical RCU implementation.
[    0.524047] rcu:     RCU lockdep checking is enabled.
[    0.524047] rcu:     RCU restricting CPUs from NR_CPUS=8192 to nr_cpu_ids=64.
[    0.524050]  Trampoline variant of Tasks RCU enabled.
[    0.524050]  Rude variant of Tasks RCU enabled.
[    0.524051]  Tracing variant of Tasks RCU enabled.
[    0.524051] rcu: RCU calculated value of scheduler-enlistment delay is 10 jiffies.
[    0.524052] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=64
[    0.524221] Running RCU synchronous self tests
[    0.524234] RCU Tasks: Setting shift to 6 and lim to 1 rcu_task_cb_adjust=1 rcu_task_cpu_ids=64.
[    0.524246] RCU Tasks Rude: Setting shift to 6 and lim to 1 rcu_task_cb_adjust=1 rcu_task_cpu_ids=64.
[    0.526613] NR_IRQS: 524544, nr_irqs: 936, preallocated irqs: 16
[    0.527079] rcu: srcu_init: Setting srcu_struct sizes based on contention.
[    0.545088] Console: colour VGA+ 80x25
[    0.545185] printk: legacy console [ttyS0] enabled
[    0.712572] Lock dependency validator: Copyright (c) 2006 Red Hat, Inc., Ingo Molnar
[    0.714245] ... MAX_LOCKDEP_SUBCLASSES:  8
[    0.715136] ... MAX_LOCK_DEPTH:          48
[    0.716043] ... MAX_LOCKDEP_KEYS:        8192
[    0.716986] ... CLASSHASH_SIZE:          4096
[    0.717930] ... MAX_LOCKDEP_ENTRIES:     32768
[    0.718893] ... MAX_LOCKDEP_CHAINS:      65536
[    0.719855] ... CHAINHASH_SIZE:          32768
[    0.720817]  memory used by lock dependency info: 6941 kB
[    0.721983]  memory used for stack traces: 4224 kB
[    0.723021]  per task-struct memory footprint: 2688 bytes
[    0.724543] ACPI: Core revision 20251212
[    0.725788] clocksource: hpet: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604467 ns
[    0.728011] APIC: Switch to symmetric I/O mode setup
[    0.729186] kvm-guest: APIC: send_IPI_mask() replaced with kvm_send_ipi_mask()
[    0.730759] kvm-guest: APIC: send_IPI_mask_allbutself() replaced with kvm_send_ipi_mask_allbutself()
[    0.732723] kvm-guest: setup PV IPIs
[    0.735620] ..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1
[    0.736987] clocksource: tsc-early: mask: 0xffffffffffffffff max_cycles: 0x257a3c3232d, max_idle_ns: 440795236700 ns
[    0.739545] Calibrating delay loop (skipped) preset value.. 5200.00 BogoMIPS (lpj=26000000)
[    0.741586] x86/cpu: User Mode Instruction Prevention (UMIP) activated
[    0.743128] Last level iTLB entries: 4KB 0, 2MB 0, 4MB 0
[    0.744284] Last level dTLB entries: 4KB 0, 2MB 0, 4MB 0, 1GB 0
[    0.745586] mitigations: Enabled attack vectors: user_kernel, user_user, SMT mitigations: auto
[    0.747452] Speculative Store Bypass: Mitigation: Speculative Store Bypass disabled via prctl
[    0.749544] Spectre V2 : Mitigation: Enhanced / Automatic IBRS
[    0.750818] ITS: Mitigation: Aligned branch/return thunks
[    0.751992] Spectre V1 : Mitigation: usercopy/swapgs barriers and __user pointer sanitization
[    0.754131] Spectre V2 : WARNING: Unprivileged eBPF is enabled with eIBRS on, data leaks possible via Spectre v2 BHB!
[    0.756702] Spectre V2 : Spectre v2 / PBRSB-eIBRS: Retire a single CALL on VMEXIT
[    0.759546] Spectre V2 : mitigation: Enabling conditional Indirect Branch Prediction Barrier
[    0.761378] active return thunk: its_return_thunk
[    0.762473] x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers'
[    0.764149] x86/fpu: Supporting XSAVE feature 0x002: 'SSE registers'
[    0.765540] x86/fpu: Supporting XSAVE feature 0x004: 'AVX registers'
[    0.766932] x86/fpu: Supporting XSAVE feature 0x020: 'AVX-512 opmask'
[    0.768342] x86/fpu: Supporting XSAVE feature 0x040: 'AVX-512 Hi256'
[    0.769550] x86/fpu: Supporting XSAVE feature 0x080: 'AVX-512 ZMM_Hi256'
[    0.771024] x86/fpu: Supporting XSAVE feature 0x20000: 'AMX Tile config'
[    0.772505] x86/fpu: Supporting XSAVE feature 0x40000: 'AMX Tile data'
[    0.773939] x86/fpu: xstate_offset[2]:  576, xstate_sizes[2]:  256
[    0.775293] x86/fpu: xstate_offset[5]:  832, xstate_sizes[5]:   64
[    0.776653] x86/fpu: xstate_offset[6]:  896, xstate_sizes[6]:  512
[    0.778004] x86/fpu: xstate_offset[7]: 1408, xstate_sizes[7]: 1024
[    0.779542] x86/fpu: xstate_offset[17]: 2432, xstate_sizes[17]:   64
[    0.780936] x86/fpu: xstate_offset[18]: 2496, xstate_sizes[18]: 8192
[    0.782326] x86/fpu: Enabled xstate features 0x600e7, context size is 10688 bytes, using 'compacted' format.
[    0.812589] pid_max: default: 65536 minimum: 512
[    0.814516] Mount-cache hash table entries: 131072 (order: 8, 1048576 bytes, linear)
[    0.816447] Mountpoint-cache hash table entries: 131072 (order: 8, 1048576 bytes, linear)
[    0.818783] VFS: Finished mounting rootfs on nullfs
[    0.821061] Running RCU synchronous self tests
[    0.822043] Running RCU synchronous self tests
[    0.823733] smpboot: CPU0: Intel INTEL(R) XEON(R) PLATINUM 8582C (family: 0x6, model: 0xcf, stepping: 0x2)
[    0.826912] Performance Events: PEBS fmt0-, Sapphire Rapids events,
[    0.826989] core: The event 0x400 is not supported as a normal event.
[    0.829539] core: The event 0x8000 is not supported as a normal event.
[    0.829539] core: The event 0x8100 is not supported as a normal event.
[    0.829539] core: The event 0x8200 is not supported as a normal event.
[    0.829564] core: The event 0x8300 is not supported as a normal event.
[    0.830989] core: The event 0x8400 is not supported as a normal event.
[    0.832414] core: The event 0x8500 is not supported as a normal event.
[    0.833840] core: The event 0x8600 is not supported as a normal event.
[    0.835264] core: The event 0x8700 is not supported as a normal event.
[    0.836711] full-width counters, Intel PMU driver.
[    0.837799] ... version:                   2
[    0.838740] ... bit width:                 48
[    0.839545] ... generic counters:          8
[    0.840533] ... generic bitmap:            00000000000000ff
[    0.841833] ... fixed-purpose counters:    3
[    0.842778] ... fixed-purpose bitmap:      0000000000000007
[    0.844001] ... value mask:                0000ffffffffffff
[    0.845231] ... max period:                00007fffffffffff
[    0.846457] ... global_ctrl mask:          00000007000000ff
[    0.848730] signal: max sigframe size: 11952
[    0.849795] rcu: Hierarchical SRCU implementation.
[    0.850848] rcu:     Max phase no-delay instances is 1000.
[    0.852229] Timer migration: 2 hierarchy levels; 8 children per group; 2 crossnode level
[    0.862598] smp: Bringing up secondary CPUs ...
[    0.864188] smpboot: x86: Booting SMP configuration:
[    0.865296] .... node  #0, CPUs:        #2  #4  #6  #8 #10 #12 #14 #16 #18 #20 #22 #24 #26 #28 #30 #32 #34 #36 #38 #3
[    0.960164] smp: Brought up 1 node, 64 CPUs
[    0.966568] smpboot: Total of 64 processors activated (332800.00 BogoMIPS)
[    0.977612] Memory: 65590812K/67108308K available (15072K kernel code, 59652K rwdata, 14884K rodata, 5692K init, 287)
[    0.989848] devtmpfs: initialized
[    0.990688] x86/mm: Memory block size: 1024MB
[    1.003627] Running RCU synchronous self tests
[    1.003627] Running RCU synchronous self tests
[    1.011501] Running RCU Tasks wait API self tests
[    1.011501] Running RCU Tasks Rude wait API self tests
[    1.011501] Running RCU Tasks Trace wait API self tests
[    1.015337] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    1.015337] posixtimers hash table entries: 32768 (order: 10, 2621440 bytes, linear)
[    1.021312] futex hash table entries: 16384 (2097152 bytes on 1 NUMA nodes, total 2048 KiB, linear).
[    1.024907] NET: Registered PF_NETLINK/PF_ROUTE protocol family
[    1.027638] audit: initializing netlink subsys (disabled)
[    1.028959] audit: type=2000 audit(1780456802.589:1): state=initialized audit_enabled=0 res=1
[    1.030231] thermal_sys: Registered thermal governor 'step_wise'
[    1.030234] thermal_sys: Registered thermal governor 'user_space'
[    1.034918] cpuidle: using governor ladder
[    1.034918] cpuidle: using governor menu
[    1.034918] Freeing SMP alternatives memory: 36K
[    1.039668] PCI: Using configuration type 1 for base access
[    1.042036] kprobes: kprobe jump-optimization is enabled. All kprobes are optimized if possible.
[    1.045883] HugeTLB: registered 1.00 GiB page size, pre-allocated 0 pages
[    1.045883] HugeTLB: 16380 KiB vmemmap can be freed for a 1.00 GiB page
[    1.049553] HugeTLB: registered 2.00 MiB page size, pre-allocated 0 pages
[    1.051532] Callback from call_rcu_tasks_trace() invoked.
[    1.051043] HugeTLB: 28 KiB vmemmap can be freed for a 2.00 MiB page
[    1.053828] ACPI: Added _OSI(Module Device)
[    1.053883] ACPI: Added _OSI(Processor Device)
[    1.054868] ACPI: Added _OSI(Processor Aggregator Device)
[    1.064769] ACPI: 1 ACPI AML tables successfully acquired and loaded
[    1.078119] ACPI: \_SB_: platform _OSC: OS support mask [00027cee]
[    1.081088] ACPI: Interpreter enabled
[    1.081938] ACPI: PM: (supports S0 S5)
[    1.082771] ACPI: Using IOAPIC for interrupt routing
[    1.083920] PCI: Using host bridge windows from ACPI; if necessary, use "pci=nocrs" and report a bug
[    1.085902] PCI: Using E820 reservations for host bridge windows
[    1.088003] ACPI: Enabled 2 GPEs in block 00 to 0F
[    1.115871] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
[    1.117249] acpi PNP0A03:00: _OSC: OS supports [ASPM ClockPM Segments MSI HPX-Type3]
[    1.118936] acpi PNP0A03:00: _OSC: not requesting OS control; OS requires [ExtendedConfig ASPM ClockPM MSI]
[    1.119556] acpi PNP0A03:00: _OSC: platform retains control of PCIe features (AE_ERROR)
[    1.121344] acpi PNP0A03:00: fail to add MMCONFIG information, can't access extended configuration space under this e
[    1.124674] PCI host bridge to bus 0000:00
[    1.125586] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
[    1.127064] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
[    1.128543] pci_bus 0000:00: root bus resource [mem 0x000a0000-0x000bffff window]
[    1.129551] pci_bus 0000:00: root bus resource [mem 0xc0000000-0xfebfffff window]
[    1.131188] pci_bus 0000:00: root bus resource [mem 0x1040000000-0x10bfffffff window]
[    1.132896] pci_bus 0000:00: root bus resource [bus 00-ff]
[    1.134218] pci 0000:00:00.0: calling  quirk_mmio_always_on+0x0/0x20 @ 1
[    1.135689] pci 0000:00:00.0: quirk_mmio_always_on+0x0/0x20 took 0 usecs
[    1.137243] pci 0000:00:00.0: [8086:1237] type 00 class 0x060000 conventional PCI endpoint
[    1.141483] pci 0000:00:01.0: [8086:7000] type 00 class 0x060100 conventional PCI endpoint
[    1.145603] pci 0000:00:01.1: [8086:7010] type 00 class 0x010180 conventional PCI endpoint
[    1.150929] pci 0000:00:01.1: BAR 4 [io  0xc1c0-0xc1cf]
[    1.152154] pci 0000:00:01.1: BAR 0 [io  0x01f0-0x01f7]: legacy IDE quirk
[    1.153652] pci 0000:00:01.1: BAR 1 [io  0x03f6]: legacy IDE quirk
[    1.155011] pci 0000:00:01.1: BAR 2 [io  0x0170-0x0177]: legacy IDE quirk
[    1.156520] pci 0000:00:01.1: BAR 3 [io  0x0376]: legacy IDE quirk
[    1.158329] pci 0000:00:01.3: calling  acpi_pm_check_blacklist+0x0/0x50 @ 1
[    1.159550] pci 0000:00:01.3: acpi_pm_check_blacklist+0x0/0x50 took 0 usecs
[    1.161081] pci 0000:00:01.3: [8086:7113] type 00 class 0x068000 conventional PCI endpoint
[    1.163375] pci 0000:00:01.3: calling  quirk_piix4_acpi+0x0/0x180 @ 1
[    1.164802] pci 0000:00:01.3: quirk: [io  0x0600-0x063f] claimed by PIIX4 ACPI
[    1.166487] pci 0000:00:01.3: quirk: [io  0x0700-0x070f] claimed by PIIX4 SMB
[    1.168111] pci 0000:00:01.3: quirk_piix4_acpi+0x0/0x180 took 9765 usecs
[    1.169546] pci 0000:00:01.3: calling  pci_fixup_piix4_acpi+0x0/0x20 @ 1
[    1.171016] pci 0000:00:01.3: pci_fixup_piix4_acpi+0x0/0x20 took 0 usecs
[    1.173137] pci 0000:00:02.0: [1af4:1000] type 00 class 0x020000 conventional PCI endpoint
[    1.179559] pci 0000:00:02.0: BAR 0 [io  0xc180-0xc19f]
[    1.180853] pci 0000:00:02.0: BAR 1 [mem 0xfc052000-0xfc052fff]
[    1.182206] pci 0000:00:02.0: BAR 4 [mem 0xfebf0000-0xfebf3fff 64bit pref]
[    1.183723] pci 0000:00:02.0: ROM [mem 0xfc000000-0xfc03ffff pref]
[    1.187574] pci 0000:00:03.0: [1b36:0100] type 00 class 0x030000 conventional PCI endpoint
[    1.204337] pci 0000:00:03.0: BAR 0 [mem 0xf0000000-0xf7ffffff]
[    1.205831] pci 0000:00:03.0: BAR 1 [mem 0xf8000000-0xfbffffff]
[    1.207180] pci 0000:00:03.0: BAR 2 [mem 0xfc050000-0xfc051fff]
[    1.208580] pci 0000:00:03.0: BAR 3 [io  0xc1a0-0xc1bf]
[    1.209579] pci 0000:00:03.0: ROM [mem 0xfc040000-0xfc04ffff pref]
[    1.211034] pci 0000:00:03.0: calling  screen_info_fixup_lfb+0x0/0x170 @ 1
[    1.212558] pci 0000:00:03.0: screen_info_fixup_lfb+0x0/0x170 took 0 usecs
[    1.214076] pci 0000:00:03.0: calling  pci_fixup_video+0x0/0x110 @ 1
[    1.215512] pci 0000:00:03.0: Video device with shadowed ROM at [mem 0x000c0000-0x000dffff]
[    1.217345] pci 0000:00:03.0: pci_fixup_video+0x0/0x110 took 0 usecs
[    1.220945] pci 0000:00:04.0: [1af4:1001] type 00 class 0x010000 conventional PCI endpoint
[    1.229567] pci 0000:00:04.0: BAR 0 [io  0xc000-0xc07f]
[    1.230839] pci 0000:00:04.0: BAR 1 [mem 0xfc053000-0xfc053fff]
[    1.232304] pci 0000:00:04.0: BAR 4 [mem 0xfebf4000-0xfebf7fff 64bit pref]
[    1.236563] pci 0000:00:05.0: [1af4:1001] type 00 class 0x010000 conventional PCI endpoint
[    1.251930] pci 0000:00:05.0: BAR 0 [io  0xc080-0xc0ff]
[    1.253130] pci 0000:00:05.0: BAR 1 [mem 0xfc054000-0xfc054fff]
[    1.254617] pci 0000:00:05.0: BAR 4 [mem 0xfebf8000-0xfebfbfff 64bit pref]
[    1.258786] pci 0000:00:06.0: [1af4:1001] type 00 class 0x010000 conventional PCI endpoint
[    1.269664] pci 0000:00:06.0: BAR 0 [io  0xc100-0xc17f]
[    1.270890] pci 0000:00:06.0: BAR 1 [mem 0xfc055000-0xfc055fff]
[    1.272368] pci 0000:00:06.0: BAR 4 [mem 0xfebfc000-0xfebfffff 64bit pref]
[    1.279844] ACPI: PCI: Interrupt link LNKA configured for IRQ 10
[    1.281679] ACPI: PCI: Interrupt link LNKB configured for IRQ 10
[    1.283351] ACPI: PCI: Interrupt link LNKC configured for IRQ 11
[    1.285032] ACPI: PCI: Interrupt link LNKD configured for IRQ 11
[    1.286503] ACPI: PCI: Interrupt link LNKS configured for IRQ 9
[    1.311447] PCI: Using ACPI for IRQ routing
[    1.312408] e820: register RAM buffer resource [mem 0x0009fc00-0x0009ffff]
[    1.312408] e820: register RAM buffer resource [mem 0xbffd7000-0xbfffffff]
[    1.316084] pci 0000:00:03.0: vgaarb: setting as boot VGA device
[    1.316084] pci 0000:00:03.0: vgaarb: bridge control possible
[    1.316084] pci 0000:00:03.0: vgaarb: VGA device added: decodes=io+mem,owns=io+mem,locks=none
[    1.316084] vgaarb: loaded
[    1.316084] hpet0: at MMIO 0xfed00000, IRQs 2, 8, 0
[    1.319548] hpet0: 3 comparators, 64-bit 100.000000 MHz counter
[    1.329544] clocksource: Switched to clocksource kvm-clock
[    1.332816] pnp: PnP ACPI init
[    1.334738] pnp: PnP ACPI: found 5 devices
[    1.342651] Callback from call_rcu_tasks() invoked.
[    1.348725] clocksource: acpi_pm: mask: 0xffffff max_cycles: 0xffffff, max_idle_ns: 2085701024 ns
[    1.351007] NET: Registered PF_INET protocol family
[    1.352536] IP idents hash table entries: 262144 (order: 9, 2097152 bytes, linear)
[    1.357256] tcp_listen_portaddr_hash hash table entries: 32768 (order: 10, 2621440 bytes, linear)
[    1.360367] Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
[    1.362098] TCP established hash table entries: 524288 (order: 10, 4194304 bytes, linear)
[    1.364687] TCP bind hash table entries: 65536 (order: 12, 10485760 bytes, vmalloc hugepage)
[    1.370412] TCP: Hash tables configured (established 524288 bind 65536)
[    1.372235] UDP hash table entries: 32768 (order: 12, 9961472 bytes, vmalloc hugepage)
[    1.377574] NET: Registered PF_UNIX/PF_LOCAL protocol family
[    1.378911] pci_bus 0000:00: resource 4 [io  0x0000-0x0cf7 window]
[    1.380274] pci_bus 0000:00: resource 5 [io  0x0d00-0xffff window]
[    1.381630] pci_bus 0000:00: resource 6 [mem 0x000a0000-0x000bffff window]
[    1.383155] pci_bus 0000:00: resource 7 [mem 0xc0000000-0xfebfffff window]
[    1.384669] pci_bus 0000:00: resource 8 [mem 0x1040000000-0x10bfffffff window]
[    1.386391] pci 0000:00:00.0: calling  quirk_passive_release+0x0/0xb0 @ 1
[    1.388018] pci 0000:00:01.0: PIIX3: Enabling Passive Release
[    1.389318] pci 0000:00:00.0: quirk_passive_release+0x0/0xb0 took 1284 usecs
[    1.390878] pci 0000:00:00.0: calling  quirk_natoma+0x0/0x40 @ 1
[    1.392209] pci 0000:00:00.0: Limiting direct PCI/PCI transfers
[    1.393533] pci 0000:00:00.0: quirk_natoma+0x0/0x40 took 1293 usecs
[    1.395026] PCI: CLS 0 bytes, default 64
[    1.396057] PCI-DMA: Using software bounce buffering for IO (SWIOTLB)
[    1.397482] software IO TLB: mapped [mem 0x00000000bbfd7000-0x00000000bffd7000] (64MB)
[    1.399313] RAPL PMU: API unit is 2^-32 Joules, 1 fixed counters, 10737418240 ms ovfl timer
[    1.401150] RAPL PMU: hw unit of domain psys 2^-0 Joules
[    1.402478] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x257a3c3232d, max_idle_ns: 440795236700 ns
[    1.448549] workingset: timestamp_bits=36 (anon: 32) max_order=24 bucket_order=0 (anon: 0)
[    1.451899] fuse: init (API version 7.45)
[    1.453726] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 253)
[    1.455376] io scheduler mq-deadline registered
[    1.456389] io scheduler kyber registered
[    1.635984] ACPI: \_SB_.LNKB: Enabled at IRQ 10
[    1.802865] ACPI: \_SB_.LNKD: Enabled at IRQ 11
[    1.975123] ACPI: \_SB_.LNKA: Enabled at IRQ 10
[    2.153578] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[    2.155816] 00:04: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A
[    2.159812] Non-volatile memory driver v1.3
[    2.160834] ACPI: bus type drm_connector registered
[    2.325622] ACPI: \_SB_.LNKC: Enabled at IRQ 11
[    2.326680] qxl 0000:00:03.0: vgaarb: deactivate vga console
[    2.343804] Console: switching to colour dummy device 80x25
[    2.345156] [drm] Device Version 0.0
[    2.345965] [drm] Compression level 0 log level 0
[    2.347194] [drm] 16382 io pages at offset 0x4000000
[    2.348298] [drm] 67108864 byte draw area at offset 0x0
[    2.349464] [drm] RAM header offset: 0x7ffe000
[    2.351527] [drm] qxl: 64M of VRAM memory size
[    2.352554] [drm] qxl: 127M of IO pages memory ready (VRAM domain)
[    2.353916] [drm] qxl: 64M of Surface memory size
[    2.355753] [drm] slot 0 (main): base 0xf0000000, size 0x07ffe000
[    2.357165] [drm] slot 1 (surfaces): base 0xf8000000, size 0x04000000
[    2.358612] stackdepot: allocating hash table of 1048576 entries via kvcalloc
[    2.364366] stackdepot: allocating space for 8192 stack pools via kvcalloc
[    2.367937] [drm] Initialized qxl 0.1.0 for 0000:00:03.0 on minor 0
[    2.371188] fbcon: qxldrmfb (fb0) is primary device
[    2.411789] Console: switching to colour frame buffer device 128x48
[    2.452239] qxl 0000:00:03.0: [drm] fb0: qxldrmfb frame buffer device
[    2.517669] brd: module loaded
[    2.543812] loop: module loaded
[    2.544852] virtio_blk virtio1: 64/0/0 default/read/poll queues
[    2.575178] virtio_blk virtio1: [vda] 41943040 512-byte logical blocks (21.5 GB/20.0 GiB)
[    2.606416]  vda: vda1 vda2
[    2.607820] virtio_blk virtio2: 64/0/0 default/read/poll queues
[    2.638462] virtio_blk virtio2: [vdb] 83886080 512-byte logical blocks (42.9 GB/40.0 GiB)
[    2.677292] virtio_blk virtio3: 64/0/0 default/read/poll queues
[    2.707670] virtio_blk virtio3: [vdc] 104857600 512-byte logical blocks (53.7 GB/50.0 GiB)
[    2.752515] zram: Added device: zram0
[    2.753799] tun: Universal TUN/TAP device driver, 1.6
[    2.760780] i8042: PNP: PS/2 Controller [PNP0303:KBD,PNP0f13:MOU] at 0x60,0x64 irq 1,12
[    2.764644] serio: i8042 KBD port at 0x60,0x64 irq 1
[    2.765852] serio: i8042 AUX port at 0x60,0x64 irq 12
[    2.767512] mousedev: PS/2 mouse device common for all mice
[    2.769099] rtc_cmos PNP0B00:00: RTC can wake from S4
[    2.771367] rtc_cmos PNP0B00:00: registered as rtc0
[    2.772690] rtc_cmos PNP0B00:00: setting system clock to 2026-06-03T03:20:04 UTC (1780456804)
[    2.774747] rtc_cmos PNP0B00:00: alarms up to one day, y3k, 242 bytes nvram, hpet irqs
[    2.776625] intel_pstate: CPU model not supported
[    2.777914] NET: Registered PF_PACKET protocol family
[    2.779802] input: AT Translated Set 2 keyboard as /devices/platform/i8042/serio0/input/input0
[    2.798681] IPI shorthand broadcast: enabled
[    2.822167] sched_clock: Marking stable (2620004035, 192443415)->(2821730911, -9283461)
[    2.827078] registered taskstats version 1
[    2.866001] Demotion targets for Node 0: null
[    2.867133] debug_vm_pgtable: [debug_vm_pgtable         ]: Validating architecture page table helpers
[    3.009038] page_owner is disabled
[    3.011181] netconsole: network logging started
[    3.013049] clk: Disabling unused clocks
[    3.454950] input: ImExPS/2 Generic Explorer Mouse as /devices/platform/i8042/serio1/input/input2
[    3.575954] EXT4-fs (vda2): orphan cleanup on readonly fs
[    3.577562] EXT4-fs (vda2): mounted filesystem d1a47800-9a04-4b0d-8eb5-7864b160615d ro with ordered data mode. Quota.
[    3.579635] VFS: Mounted root (ext4 filesystem) readonly on device 254:2.
[    3.581785] devtmpfs: mounted
[    3.582990] VFS: Pivoted into new rootfs
[    3.595156] Freeing unused kernel image (initmem) memory: 5692K
[    3.596195] Write protecting the kernel read-only data: 32768k
[    3.599499] Freeing unused kernel image (text/rodata gap) memory: 1308K
[    3.602043] Freeing unused kernel image (rodata/data gap) memory: 1500K
[    3.603199] Run /sbin/init as init process
[    4.007294] systemd[1]: Failed to find module 'autofs4'
[    4.084919] systemd[1]: systemd 258.7-1.fc43 running in system mode (+PAM +AUDIT +SELINUX -APPARMOR +IMA +IPE +SMACK +SECCOMP -GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN -IPTC +KMOD +LIBCRYPTSETUP +LIBCRYPTSETUP_PLUGINS +LIBFDISK +PCRE2 +PWQUALITY +P11KIT +QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD +BPF_FRAMEWORK +BTF +XKBCOMMON +UTMP +SYSVINIT +LIBARCHIVE)
[    4.090677] systemd[1]: Detected virtualization kvm.
[    4.091547] systemd[1]: Detected architecture x86-64.

Welcome to Fedora Linux 43 (Forty Three)!

[    4.101846] systemd[1]: Hostname set to <intelvm>.
[    4.207427] systemd[1]: bpf-restrict-fs: BPF LSM hook not enabled in the kernel, BPF LSM not supported.
[    4.455323] systemd[1]: Queued start job for default target multi-user.target.
[    4.508112] systemd[1]: Created slice system-getty.slice - Slice /system/getty.
[  OK  ] Created slice system-getty.slice - Slice /system/getty.
[    4.514578] systemd[1]: Created slice system-modprobe.slice - Slice /system/modprobe.
[  OK  ] Created slice system-modprobe.slice - Slice /system/modprobe.
[    4.521685] systemd[1]: Created slice system-serial\x2dgetty.slice - Slice /system/serial-getty.
[  OK  ] Created slice system-serial\x2dgetty.slice - Slice /system/serial-getty.
[    4.528832] systemd[1]: Created slice system-sshd\x2dkeygen.slice - Slice /system/sshd-keygen.
[  OK  ] Created slice system-sshd\x2dkeygen.slice - Slice /system/sshd-keygen.
[    4.536200] systemd[1]: Created slice system-systemd\x2dfsck.slice - Slice /system/systemd-fsck.
[  OK  ] Created slice system-systemd\x2dfsck.slice - Slice /system/systemd-fsck.
[    4.543365] systemd[1]: Created slice system-systemd\x2dzram\x2dsetup.slice - Slice /system/systemd-zram-setup.
[  OK  ] Created slice system-systemd\x2dzram\x2dsetup.slice - Slice /system/systemd-zram-setup.
[    4.550882] systemd[1]: Created slice user.slice - User and Session Slice.
[  OK  ] Created slice user.slice - User and Session Slice.
[    4.555350] systemd[1]: Started systemd-ask-password-wall.path - Forward Password Requests to Wall Directory Watch.
[  OK  ] Started systemd-ask-password-wall.path - Forward Password Requests to Wall Directory Watch.
[    4.561828] systemd[1]: Starting of proc-sys-fs-binfmt_misc.automount - Arbitrary Executable File Formats File System Automount Point unsupported.
[UNSUPP] Starting of proc-sys-fs-binfmt_misc.automount - Arbitr…e File Formats File System Automount Point unsupported.
[    4.569722] systemd[1]: Expecting device dev-disk-by\x2duuid-d44c9a9e\x2d67bc\x2d4f32\x2dad5f\x2ddec10c152dba.device - /dev/disk/by-uuid/d44c9a9e-67bc-4f32-ad5f-dec10c152dba...
         Expecting device dev-disk-by\x2duuid-d44c9a9e\x2d67bc\…ev/disk/by-uuid/d44c9a9e-67bc-4f32-ad5f-dec10c152dba...
[    4.577342] systemd[1]: Expecting device dev-disk-by\x2duuid-f4f6c870\x2d2da2\x2d4b25\x2d89e7\x2db335d590aa87.device - /dev/disk/by-uuid/f4f6c870-2da2-4b25-89e7-b335d590aa87...
         Expecting device dev-disk-by\x2duuid-f4f6c870\x2d2da2\…ev/disk/by-uuid/f4f6c870-2da2-4b25-89e7-b335d590aa87...
[    4.584882] systemd[1]: Expecting device dev-ttyS0.device - /dev/ttyS0...
         Expecting device dev-ttyS0.device - /dev/ttyS0...
[    4.588839] systemd[1]: Expecting device dev-zram0.device - /dev/zram0...
         Expecting device dev-zram0.device - /dev/zram0...
[    4.592707] systemd[1]: Reached target imports.target - Image Downloads.
[  OK  ] Reached target imports.target - Image Downloads.
[    4.596985] systemd[1]: Reached target integritysetup.target - Local Integrity Protected Volumes.
[  OK  ] Reached target integritysetup.target - Local Integrity Protected Volumes.
[    4.602430] systemd[1]: Reached target remote-cryptsetup.target - Remote Encrypted Volumes.
[  OK  ] Reached target remote-cryptsetup.target - Remote Encrypted Volumes.
[    4.607656] systemd[1]: Reached target remote-fs.target - Remote File Systems.
[  OK  ] Reached target remote-fs.target - Remote File Systems.
[    4.612137] systemd[1]: Reached target slices.target - Slice Units.
[  OK  ] Reached target slices.target - Slice Units.
[    4.616180] systemd[1]: Reached target veritysetup.target - Local Verity Protected Volumes.
[  OK  ] Reached target veritysetup.target - Local Verity Protected Volumes.
[    4.622724] systemd[1]: Listening on systemd-ask-password.socket - Query the User Interactively for a Password.
[  OK  ] Listening on systemd-ask-password.socket - Query the User Interactively for a Password.
[    4.630586] systemd[1]: Listening on systemd-coredump.socket - Process Core Dump Socket.
[  OK  ] Listening on systemd-coredump.socket - Process Core Dump Socket.
[    4.636880] systemd[1]: Listening on systemd-creds.socket - Credential Encryption/Decryption.
[  OK  ] Listening on systemd-creds.socket - Credential Encryption/Decryption.
[    4.643661] systemd[1]: Listening on systemd-factory-reset.socket - Factory Reset Management.
[  OK  ] Listening on systemd-factory-reset.socket - Factory Reset Management.
[    4.649540] systemd[1]: Listening on systemd-journald-audit.socket - Journal Audit Socket.
[  OK  ] Listening on systemd-journald-audit.socket - Journal Audit Socket.
[    4.654921] systemd[1]: Listening on systemd-journald-dev-log.socket - Journal Socket (/dev/log).
[  OK  ] Listening on systemd-journald-dev-log.socket - Journal Socket (/dev/log).
[    4.660671] systemd[1]: Listening on systemd-journald.socket - Journal Sockets.
[  OK  ] Listening on systemd-journald.socket - Journal Sockets.
[    4.665605] systemd[1]: Listening on systemd-oomd.socket - Userspace Out-Of-Memory (OOM) Killer Socket.
[  OK  ] Listening on systemd-oomd.socket - Userspace Out-Of-Memory (OOM) Killer Socket.
[    4.671333] systemd[1]: systemd-pcrextend.socket - TPM PCR Measurements skipped, unmet condition check ConditionSecurity=measured-uki
[    4.673386] systemd[1]: systemd-pcrlock.socket - Make TPM PCR Policy skipped, unmet condition check ConditionSecurity=measured-uki
[    4.675628] systemd[1]: Listening on systemd-resolved-monitor.socket - Resolve Monitor Varlink Socket.
[  OK  ] Listening on systemd-resolved-monitor.socket - Resolve Monitor Varlink Socket.
[    4.681438] systemd[1]: Listening on systemd-resolved-varlink.socket - Resolve Service Varlink Socket.
[  OK  ] Listening on systemd-resolved-varlink.socket - Resolve Service Varlink Socket.
[    4.687459] systemd[1]: Listening on systemd-udevd-control.socket - udev Control Socket.
[  OK  ] Listening on systemd-udevd-control.socket - udev Control Socket.
[    4.692590] systemd[1]: Listening on systemd-udevd-kernel.socket - udev Kernel Socket.
[  OK  ] Listening on systemd-udevd-kernel.socket - udev Kernel Socket.
[    4.697767] systemd[1]: Listening on systemd-udevd-varlink.socket - udev Varlink Socket.
[  OK  ] Listening on systemd-udevd-varlink.socket - udev Varlink Socket.
[    4.702921] systemd[1]: Listening on systemd-userdbd.socket - User Database Manager Socket.
[  OK  ] Listening on systemd-userdbd.socket - User Database Manager Socket.
[    4.711462] systemd[1]: Mounting dev-hugepages.mount - Huge Pages File System...
         Mounting dev-hugepages.mount - Huge Pages File System...
[    4.718261] systemd[1]: Mounting dev-mqueue.mount - POSIX Message Queue File System...
         Mounting dev-mqueue.mount - POSIX Message Queue File System...
[    4.774947] systemd[1]: Mounting sys-kernel-debug.mount - Kernel Debug File System...
         Mounting sys-kernel-debug.mount - Kernel Debug File System...
[    4.781941] systemd[1]: Mounting sys-kernel-tracing.mount - Kernel Trace File System...
         Mounting sys-kernel-tracing.mount - Kernel Trace File System...
[    4.786679] systemd[1]: kmod-static-nodes.service - Create List of Static Device Nodes skipped, unmet condition check ConditionFileNotEmpty=/lib/modules/7.1.0-rc2-00057-gb3a2dfa8b42e/modules.devname
[    4.792161] systemd[1]: Starting modprobe@configfs.service - Load Kernel Module configfs...
         Starting modprobe@configfs.service - Load Kernel Module configfs...
[    4.799728] systemd[1]: Starting modprobe@dm_mod.service - Load Kernel Module dm_mod...
         Starting modprobe@dm_mod.service - Load Kernel Module dm_mod...
[    4.804381] systemd[1]: modprobe@drm.service - Load Kernel Module drm skipped, unmet condition check ConditionKernelModuleLoaded=!drm
[    4.809310] systemd[1]: Starting modprobe@efi_pstore.service - Load Kernel Module efi_pstore...
         Starting modprobe@efi_pstore.service - Load Kernel Module efi_pstore...
[    4.814378] systemd[1]: modprobe@fuse.service - Load Kernel Module fuse skipped, unmet condition check ConditionKernelModuleLoaded=!fuse
[    4.819352] systemd[1]: Mounting sys-fs-fuse-connections.mount - FUSE Control File System...
         Mounting sys-fs-fuse-connections.mount - FUSE Control File System...
[    4.824258] systemd[1]: modprobe@loop.service - Load Kernel Module loop skipped, unmet condition check ConditionKernelModuleLoaded=!loop
[    4.829042] systemd[1]: Starting systemd-fsck-root.service - File System Check on Root Device...
         Starting systemd-fsck-root.service - File System Check on Root Device...
[    4.834146] systemd[1]: systemd-hibernate-clear.service - Clear Stale Hibernate Storage Info skipped, unmet condition check ConditionPathExists=/sys/firmware/efi/efivars/HibernateLocation-8cf2644b-4b0b-428f-9387-6d876050dc67
[    4.845545] systemd[1]: Starting systemd-journald.service - Journal Service...
         Starting systemd-journald.service - Journal Service...
[    4.853019] systemd[1]: Starting systemd-modules-load.service - Load Kernel Modules...
         Starting systemd-modules-load.service - Load Kernel Module[    4.857095] systemd[1]: Starting systemd-network-generator.service - Generate Network Units from Kernel Command Line...
s...
         Startin[    4.860242] systemd[1]: systemd-pcrmachine.service - TPM PCR Machine ID Measurement skipped, unmet condition check ConditionSecurity=measured-uki
g systemd-network-generator.service - Generate Network Units from K[    4.866131] systemd[1]: Starting systemd-tmpfiles-setup-dev-early.service - Create Static Device Nodes in /dev gracefully...
ernel Command Line...
         Startin[    4.869325] systemd[1]: systemd-tpm2-setup-early.service - Early TPM SRK Setup skipped, unmet condition check ConditionSecurity=measured-uki
g systemd-tmpfiles-setup-dev-early.service - Create Static Device N[    4.874603] systemd[1]: Starting systemd-udev-load-credentials.service - Load udev Rules from Credentials...
odes in /dev gracefully...
         Starting systemd-udev-load-credentials.service - Load udev Rules from Credentials...
[    4.884678] systemd[1]: Starting systemd-udev-trigger.service - Coldplug All udev Devices...
         Starting syste[    4.887424] systemd-journald[488]: Collecting audit messages is enabled.
md-udev-trigger.service - Coldplug All udev Devices...
[    4.893492] systemd[1]: Starting systemd-vconsole-setup.service - Virtual Console Setup...
         Starting systemd-vconsole-setup.service - Virtual Console Setup...
[    4.904874] systemd[1]: Mounted dev-hugepages.mount - Huge Pages File System.
[  OK  ] Mounted dev-hugepages.mount - Huge Pages File System.
[    4.909825] systemd[1]: Mounted dev-mqueue.mount - POSIX Message Queue File System.
[  OK  ] Mounted dev-mqueue.mount - POSIX Message Queue File System.
[    4.915101] systemd[1]: Mounted sys-kernel-debug.mount - Kernel Debug File System.
[  OK      4.916777] systemd[1]: Mounted sys-kernel-tracing.mount - Kernel Trace File System.
0m] Mounted sys-kernel-debug.mount - Kernel Debug F[    4.920580] systemd[1]: modprobe@configfs.service: Deactivated successfully.
ile System.
[  OK  ] Mounted sys-kernel-tr[    4.924013] systemd[1]: Finished modprobe@configfs.service - Load Kernel Module configfs.
acing.mount - Kernel Trace File System.
[ audit: type=1130 audit(1780456806.640:2): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=modprobe@configfs comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
[    4.928306] systemd[1]: modprobe@dm_mod.service: Deactivated successfully.
[0;32m  OK  [    4.930905] audit: type=1131 audit(1780456806.640:3): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=modprobe@configfs comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
[    4.933555] systemd[1]: Finished modprobe@dm_mod.service - Load Kernel Module dm_mod.
] Finished modprobe@configfs.service - Load Kernel Module configfs.
[  OK      4.944989] audit: type=1130 audit(1780456806.660:4): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=modprobe@dm_mod comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
[    4.945000] audit: type=1131 audit(1780456806.660:5): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=modprobe@dm_mod comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
0m] Finished     4.945975] systemd[1]: modprobe@efi_pstore.service: Deactivated successfully.
;1;39mmodprobe@d[    4.947284] systemd[1]: Finished modprobe@efi_pstore.service - Load Kernel Module efi_pstore.
[    4.957158] audit: type=1130 audit(1780456806.670:6): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=modprobe@efi_pstore comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'

[  OK   systemd[1]: Mounted sys-fs-fuse-connections.mount - FUSE Control File System.
[0m] Finished     4.961189] audit: type=1131 audit(1780456806.670:7): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=modprobe@efi_pstore comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
0;1;39mmodprobe@efi_pstore.service - Load Kernel Module efi_pstore.
[  OK  ] Mounted sys-fs-fuse-connections.mount - FUSE Control File System.
[    4.973499] systemd[1]: Finished systemd-fsck-root.service - File System Check on Root Device.
[  OK      4.975108] audit: type=1130 audit(1780456806.690:8): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=systemd-fsck-root comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
[    4.976356] systemd[1]: Started systemd-journald.service - Journal Service.
0m] Finished systemd-fsck-root.service audit: type=1130 audit(1780456806.690:9): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=systemd-journald comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
[0m - File System Check on Root Device.
[    4.986012] audit: type=1130 audit(1780456806.700:10): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=systemd-modules-load comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
2m  OK  ] Started systemd-journald.service - Journal Service.
[  OK  ] Finished systemd-modules-load.service - Load Kernel Modules.
[  OK  ] Finished systemd-network-generator.service - Generate Network Units from Kernel Command Line.
[  OK  ] Finished systemd-udev-load-credentials.service - Load udev Rules from Credentials.
[  OK  ] Finished systemd-vconsole-setup.service - Virtual Console Setup.
         Starting systemd-remount-fs.service - Remount Root and Kernel File Systems...
         Starting systemd-sysctl.service - Apply Kernel Variables...
         Starting systemd-userdbd.service - User Database Manager...
[  OK  ] Finished systemd-sysctl.service - Apply Kernel Variables.
[  OK  ] Started systemd-userdbd.service - User Database Manager.
[  OK  ] Finished systemd-tmpfiles-setup-dev-early.service - Create Static Device Nodes in /dev gracefully.
[    5.374873] EXT4-fs (vda2): re-mounted d1a47800-9a04-4b0d-8eb5-7864b160615d r/w.
[  OK  ] Finished systemd-remount-fs.service - Remount Root and Kernel File Systems.
         Starting systemd-journal-flush.service - Flush Journal to Persistent Storage...
         Starting systemd-random-seed.service - Load/Save OS Random Seed...
         Starting systemd-tmpfiles-setu[    5.521116] systemd-journald[488]: Received client request to flush runtime journal.
p-dev.service - Create Static Device Nodes in /dev...
[  OK  ] Finished systemd-random-seed.service - Load/Save OS Random Seed.
[  OK  ] Finished systemd-udev-trigger.service - Coldplug All udev Devices.
[  OK  ] Finished systemd-tmpfiles-setup-dev.service - Create Static Device Nodes in /dev.
[  OK  ] Reached target local-fs-pre.target - Preparation for Local File Systems.
         Starting systemd-udevd.service - Rule-based Manager for Device Events and Files...
[  OK  ] Finished systemd-journal-flush.service - Flush Journal to Persistent Storage.
[  OK  ] Started systemd-udevd.service - Rule-based Manager for Device Events and Files.
         Starting plymouth-start.service - Show Plymouth Boot Screen...
[  OK  ] Started plymouth-start.service - Show Plymouth Boot Screen.
[  OK  ] Started systemd-ask-password-plymouth.path - Forward Password Requests to Plymouth Directory Watch.
[  OK  ] Reached target cryptsetup.target - Local Encrypted Volumes.
[  OK  ] Reached target paths.target - Path Units.
virtio_net virtio0 ens2: renamed from eth0
[  OK  ] Found device dev-zram0.device - /dev/zram0.
[  OK  ] Found device dev-disk-by\x2duuid-f4f6c870\x2d2da2\x2d4…/dev/disk/by-uuid/f4f6c870-2da2-4b25-89e7-b335d590aa87.
[  OK  ] Found device dev-disk-by\x2duuid-d44c9a9e\x2d67bc\x2d4…/dev/disk/by-uuid/d44c9a9e-67bc-4f32-ad5f-dec10c152dba.
[  OK  ] Found device dev-ttyS0.device - /dev/ttyS0.
         Starting systemd-fsck@dev-disk-by\x2duuid-d44c9a9e\x2d…ev/disk/by-uuid/d44c9a9e-67bc-4f32-ad5f-dec10c152dba...
         Starting systemd-fsck@dev-disk-by\x2duuid-f4f6c870\x2d…ev/disk/by-uuid/f4f6c870-2da2-4b25-89e7-b335d590aa87...
[  OK  ] Stopped systemd-vconsole-setup.service - Virtual Console Setup.
         Stopping systemd-vconsole-setup.service - Virtual Console Setup...
kauditd_printk_skb: 18 callbacks suppressed
audit: type=1131 audit(1780456808.080:29): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=systemd-vconsole-setup comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
         Starting systemd-vconsole-setup.service - Virtual Console Setup...
         Starting systemd-zram-setup@zram0.service - Create swap on /dev/zram0...
[  OK  ] Finished systemd-fsck@dev-disk-by\x2duuid-d44c9a9e\x2d…/dev/disk/by-uuid/d44c9a9e-67bc-4f32-ad5f-dec10c152dba.
audit: type=1130 audit(1780456808.270:30): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=systemd-fsck@dev-disk-by\x2duuid-d44c9a9e\x2d67bc\x2d4f32\x2dad5f\x2ddec10c152dba comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
[  OK  ] Finished systemd-fsck@dev-disk-by\x2duuid-f4f6c870\x2d…/dev/disk/by-uuid/f4f6c870-2da2-4b25-89e7-b335d590aa87.
zram0: detected capacity change from 0 to 16777216
audit: type=1130 audit(1780456808.290:31): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=systemd-fsck@dev-disk-by\x2duuid-f4f6c870\x2d2da2\x2d4b25\x2d89e7\x2db335d590aa87 comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
         Mounting home.mount - /home...
[  OK  ] Finished systemd-zram-setup@zram0.service - Create swap on /dev/zram0.
         Activating swap dev-zram0.swap - Compressed Swap on /dev/zram0...
audit: type=1130 audit(1780456808.310:32): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=systemd-zram-setup@zram0 comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
[  OK  ] Finished systemd-vconsole-setup.service - Virtual Console Setup.
audit: type=1130 audit(1780456808.340:33): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=systemd-vconsole-setup comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
EXT4-fs (vdb): mounted filesystem d44c9a9e-67bc-4f32-ad5f-dec10c152dba r/w with ordered data mode. Quota mode: disabled.
[  OK  ] Mounted home.mount - /home.
         Mounting home-aaron-linux.mount - /home/aaron/linux...
[  OK  ] Mounted home-aaron-linux.mount - /home/aaron/linux.
EXT4-fs (vdc): mounted filesystem f4f6c870-2da2-4b25-89e7-b335d590aa87 r/w with ordered data mode. Quota mode: disabled.
[  OK  ] Activated swap dev-zram0.swap - Compressed Swap on /dev/zram0.
[  OK  ] Reached target swap.target - Swaps.
Adding 8388604k swap on /dev/zram0.  Priority:100 extents:1 across:8388604k SSDsc
         Mounting tmp.mount - Temporary Directory /tmp...
[  OK  ] Mounted tmp.mount - Temporary Directory /tmp.
[  OK  ] Reached target local-fs.target - Local File Systems.
[  OK  ] Listening on systemd-bootctl.socket - Boot Entries Service Socket.
[  OK  ] Listening on systemd-sysext.socket - System Extension Image Management.
         Starting plymouth-read-write.service - Tell Plymouth To Write Out Runtime Data...
         Starting systemd-tmpfiles-setup.service - Create System Files and Directories...
         Starting systemd-userdb-load-credentials.service - Load JSON user/group Records from Credentials...
[  OK  ] Finished plymouth-read-write.service - Tell Plymouth To Write Out Runtime Data.
audit: type=1130 audit(1780456809.070:34): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=plymouth-read-write comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
[  OK  ] Finished systemd-userdb-load-credentials.service - Load JSON user/group Records from Credentials.
audit: type=1130 audit(1780456809.090:35): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=systemd-userdb-load-credentials comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
[  OK  ] Finished systemd-tmpfiles-setup.service - Create System Files and Directories.
         Starting auditd.service - Security Audit Logging Service...
audit: type=1130 audit(1780456809.200:36): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=systemd-tmpfiles-setup comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
audit: type=1334 audit(1780456809.200:37): prog-id=22 op=LOAD
audit: type=1334 audit(1780456809.200:38): prog-id=23 op=LOAD
         Starting systemd-oomd.service - Userspace Out-Of-Memory (OOM) Killer...
         Starting systemd-resolved.service - Network Name Resolution...
[  OK  ] Started auditd.service - Security Audit Logging Service.
         Starting audit-rules.service - Load Audit Rules...
         Starting systemd-update-utmp.service - Record System Boot/Shutdown in UTMP...
[  OK  ] Finished systemd-update-utmp.service - Record System Boot/Shutdown in UTMP.
[  OK  ] Finished audit-rules.service - Load Audit Rules.
[  OK  ] Started systemd-oomd.service - Userspace Out-Of-Memory (OOM) Killer.
[  OK  ] Started systemd-resolved.service - Network Name Resolution.
[  OK  ] Reached target nss-lookup.target - Host and Network Name Lookups.
[  OK  ] Reached target sysinit.target - System Initialization.
[  OK  ] Started fstrim.timer - Discard unused filesystem blocks once a week.
[  OK  ] Started logrotate.timer - Daily rotation of log files.
[  OK  ] Started raid-check.timer - Weekly RAID setup health check.
[  OK  ] Started sysstat-collect.timer - Run system activity accounting tool every 10 minutes.
[  OK  ] Started sysstat-rotate.timer - Rotate daily system activity data file at midnight.
[  OK  ] Started sysstat-summary.timer - Generate summary of yesterday's process accounting.
[  OK  ] Started systemd-tmpfiles-clean.timer - Daily Cleanup of Temporary Directories.
[  OK  ] Started unbound-anchor.timer - daily update of the root trust anchor for DNSSEC.
[  OK  ] Reached target timers.target - Timer Units.
[  OK  ] Listening on avahi-daemon.socket - Avahi mDNS/DNS-SD Stack Activation Socket.
[  OK  ] Listening on dbus.socket - D-Bus System Message Bus Socket.
[  OK  ] Listening on pcscd.socket - PC/SC Smart Card Daemon Activation Socket.
[  OK  ] Listening on sshd-unix-local.socket - OpenSSH Server Socket (systemd-ssh-generator, AF_UNIX Local).
[  OK  ] Listening on systemd-hostnamed.socket - Hostname Service Socket.
[  OK  ] Listening on systemd-logind-varlink.socket - User Login Management Varlink Socket.
[  OK  ] Reached target sockets.target - Socket Units.
         Starting dbus-broker.service - D-Bus System Message Bus...
[  OK  ] Started dbus-broker.service - D-Bus System Message Bus.
[  OK  ] Reached target basic.target - Basic System.
         Starting avahi-daemon.service - Avahi mDNS/DNS-SD Stack...
         Starting chronyd.service - NTP client/server...
         Starting dracut-shutdown.service - Restore /run/initramfs on shutdown...
         Starting firewalld.service - firewalld - dynamic firewall daemon...
[  OK  ] Reached target sshd-keygen.target.
clocksource: Watchdog remote CPU 12 read timed out
         Starting sysstat.service - Resets System Activity Logs...
         Starting systemd-homed.service - Home Area Manager...
         Starting systemd-logind.service - User Login Management...
[  OK  ] Finished dracut-shutdown.service - Restore /run/initramfs on shutdown.
[  OK  ] Finished sysstat.service - Resets System Activity Logs.
[  OK  ] Started avahi-daemon.service - Avahi mDNS/DNS-SD Stack.
[  OK  ] Started systemd-homed.service - Home Area Manager.
[  OK  ] Finished systemd-homed-activate.service - Home Area Activation.
[  OK  ] Started systemd-logind.service - User Login Management.
[FAILED] Failed to start chronyd.service - NTP client/server.
See 'systemctl status chronyd.service' for details.
[FAILED] Failed to start firewalld.service - firewalld - dynamic firewall daemon.
See 'systemctl status firewalld.service' for details.
[  OK  ] Reached target network-pre.target - Preparation for Network.
         Starting NetworkManager.service - Network Manager...
         Starting systemd-hostnamed.service - Hostname Service...
[  OK  ] Started systemd-hostnamed.service - Hostname Service.
         Starting NetworkManager-dispatcher.service - Network Manager Script Dispatcher Service...
[  OK  ] Started NetworkManager.service - Network Manager.
[  OK  ] Reached target network.target - Network.
         Starting kdump.service - Crash recovery kernel arming...
         Starting sshd.service - OpenSSH server daemon...
         Starting systemd-user-sessions.service - Permit User Sessions...
[  OK  ] Started NetworkManager-dispatcher.service - Network Manager Script Dispatcher Service.
[  OK  ] Finished systemd-user-sessions.service - Permit User Sessions.
         Starting plymouth-quit-wait.service - Hold until boot process finishes up...
         Starting plymouth-quit.service - Terminate Plymouth Boot Screen...
[  OK  ] Started sshd.service - OpenSSH server daemon.

Fedora Linux 43 (Forty Three)
Kernel 7.1.0-rc2-00057-gb3a2dfa8b42e on x86_64 (ttyS0)

intelvm login: [   26.082516] ------------[ cut here ]------------
[   26.082721]
[   26.082722] ======================================================
[   26.082723] WARNING: possible circular locking dependency detected
[   26.082724] 7.1.0-rc2-00057-gb3a2dfa8b42e #44 Not tainted
[   26.082725] ------------------------------------------------------
[   26.082726] kworker/57:1/414 is trying to acquire lock:
[   26.082727] ffffffff83071220 (console_owner){....}-{0:0}, at: console_lock_spinning_enable+0x40/0x70
[   26.082735]
[   26.082735] but task is already holding lock:
[   26.082736] ff11000ffddfdc60 (&rq->__lock){-.-.}-{2:2}, at: raw_spin_rq_lock_nested+0x53/0xa0
[   26.082740]
[   26.082740] which lock already depends on the new lock.
[   26.082740]
[   26.082741]
[   26.082741] the existing dependency chain (in reverse order) is:
[   26.082741]
[   26.082741] -> #4 (&rq->__lock){-.-.}-{2:2}:
[   26.082743]        __lock_acquire+0x6e5/0xc70
[   26.082745]        lock_acquire+0xc7/0x2d0
[   26.082749]        _raw_spin_lock_nested+0x32/0x80
[   26.082752]        raw_spin_rq_lock_nested+0x26/0xa0
[   26.082754]        _task_rq_lock+0x49/0x110
[   26.082755]        cgroup_move_task+0x35/0x120
[   26.082758]        css_set_move_task+0xe8/0x240
[   26.082762]        cgroup_post_fork+0x96/0x290
[   26.082764]        copy_process+0x180a/0x1bd0
[   26.082766]        kernel_clone+0xae/0x3b0
[   26.082768]        user_mode_thread+0x61/0x90
[   26.082769]        rest_init+0x1e/0x190
[   26.082771]        start_kernel+0x6c1/0x770
[   26.082774]        x86_64_start_reservations+0x18/0x30
[   26.082776]        x86_64_start_kernel+0xd3/0xe0
[   26.082777]        common_startup_64+0x12c/0x138
[   26.082781]
[   26.082781] -> #3 (&p->pi_lock){-.-.}-{2:2}:
[   26.082782]        __lock_acquire+0x6e5/0xc70
[   26.082783]        lock_acquire+0xc7/0x2d0
[   26.082786]        _raw_spin_lock_irqsave+0x43/0x90
[   26.082788]        try_to_wake_up+0x5a/0x710
[   26.082790]        __wake_up_common+0x82/0xc0
[   26.082793]        __wake_up+0x36/0x60
[   26.082795]        tty_port_default_wakeup+0x2d/0x40
[   26.082799]        serial8250_tx_chars+0x35c/0x3a0
[   26.082802]        serial8250_handle_irq+0x47/0x140
[   26.082803]        serial8250_interrupt+0x5a/0xb0
[   26.082805]        __handle_irq_event_percpu+0x90/0x340
[   26.082808]        handle_irq_event+0x38/0x80
[   26.082809]        handle_edge_irq+0xbe/0x1a0
[   26.082811]        __common_interrupt+0x4d/0x130
[   26.082815]        common_interrupt+0x78/0xa0
[   26.082817]        asm_common_interrupt+0x26/0x40
[   26.082819]        pv_native_safe_halt+0xf/0x20
[   26.082821]        default_idle+0x9/0x10
[   26.082822]        default_idle_call+0x83/0x200
[   26.082824]        cpuidle_idle_call+0x16a/0x1a0
[   26.082826]        do_idle+0x93/0xd0
[   26.082827]        cpu_startup_entry+0x29/0x30
[   26.082829]        start_secondary+0xf8/0x100
[   26.082832]        common_startup_64+0x12c/0x138
[   26.082834]
[   26.082834] -> #2 (&tty->write_wait){-.-.}-{3:3}:
[   26.082835]        __lock_acquire+0x6e5/0xc70
[   26.082836]        lock_acquire+0xc7/0x2d0
[   26.082839]        _raw_spin_lock_irqsave+0x43/0x90
[   26.082841]        __wake_up+0x21/0x60
[   26.082842]        tty_port_default_wakeup+0x2d/0x40
[   26.082844]        serial8250_tx_chars+0x35c/0x3a0
[   26.082845]        serial8250_handle_irq+0x47/0x140
[   26.082846]        serial8250_interrupt+0x5a/0xb0
[   26.082848]        __handle_irq_event_percpu+0x90/0x340
[   26.082849]        handle_irq_event+0x38/0x80
[   26.082851]        handle_edge_irq+0xbe/0x1a0
[   26.082852]        __common_interrupt+0x4d/0x130
[   26.082854]        common_interrupt+0x78/0xa0
[   26.082856]        asm_common_interrupt+0x26/0x40
[   26.082857]        pv_native_safe_halt+0xf/0x20
[   26.082859]        default_idle+0x9/0x10
[   26.082860]        default_idle_call+0x83/0x200
[   26.082862]        cpuidle_idle_call+0x16a/0x1a0
[   26.082863]        do_idle+0x93/0xd0
[   26.082864]        cpu_startup_entry+0x29/0x30
[   26.082865]        start_secondary+0xf8/0x100
[   26.082867]        common_startup_64+0x12c/0x138
[   26.082869]
[   26.082869] -> #1 (&port_lock_key){-.-.}-{3:3}:
[   26.082870]        __lock_acquire+0x6e5/0xc70
[   26.082871]        lock_acquire+0xc7/0x2d0
[   26.082874]        _raw_spin_lock_irqsave+0x43/0x90
[   26.082876]        serial8250_console_write+0x8f/0x650
[   26.082877]        console_emit_next_record+0x10d/0x200
[   26.082879]        console_flush_one_record+0x223/0x330
[   26.082880]        console_unlock+0x6d/0x130
[   26.082881]        vprintk_emit+0x187/0x1c0
[   26.082883]        _printk+0x5b/0x80
[   26.082886]        register_console+0x278/0x450
[   26.082888]        univ8250_console_init+0x24/0x40
[   26.082890]        console_init+0x74/0x250
[   26.082892]        start_kernel+0x42d/0x770
[   26.082893]        x86_64_start_reservations+0x18/0x30
[   26.082895]        x86_64_start_kernel+0xd3/0xe0
[   26.082896]        common_startup_64+0x12c/0x138
[   26.082898]
[   26.082898] -> #0 (console_owner){....}-{0:0}:
[   26.082899]        check_prev_add+0xf1/0xc50
[   26.082902]        validate_chain+0x5c5/0x6f0
[   26.082904]        __lock_acquire+0x6e5/0xc70
[   26.082905]        lock_acquire+0xc7/0x2d0
[   26.082907]        console_lock_spinning_enable+0x5c/0x70
[   26.082909]        console_emit_next_record+0xcf/0x200
[   26.082910]        console_flush_one_record+0x223/0x330
[   26.082911]        console_unlock+0x6d/0x130
[   26.082912]        vprintk_emit+0x187/0x1c0
[   26.082914]        _printk+0x5b/0x80
[   26.082916]        __report_bug+0xf3/0x1f0
[   26.082919]        report_bug+0x2c/0x80
[   26.082921]        handle_bug+0x214/0x250
[   26.082922]        exc_invalid_op+0x17/0x70
[   26.082924]        asm_exc_invalid_op+0x1a/0x20
[   26.082925]        hrtick_start_fair+0x88/0xa0
[   26.082926]        __set_next_task_fair+0x1de/0x210
[   26.082928]        pick_next_task+0x6fc/0x9c0
[   26.082930]        __schedule+0x1a8/0x7d0
[   26.082932]        schedule+0x3a/0xe0
[   26.082934]        worker_thread+0xd0/0x360
[   26.082936]        kthread+0xf4/0x130
[   26.082938]        ret_from_fork+0x29f/0x330
[   26.082940]        ret_from_fork_asm+0x1a/0x30
[   26.082942]
[   26.082942] other info that might help us debug this:
[   26.082942]
[   26.082943] Chain exists of:
[   26.082943]   console_owner --> &p->pi_lock --> &rq->__lock
[   26.082943]
[   26.082945]  Possible unsafe locking scenario:
[   26.082945]
[   26.082945]        CPU0                    CPU1
[   26.082945]        ----                    ----
[   26.082946]   lock(&rq->__lock);
[   26.082946]                                lock(&p->pi_lock);
[   26.082947]                                lock(&rq->__lock);
[   26.082948]   lock(console_owner);
[   26.082949]
[   26.082949]  *** DEADLOCK ***
[   26.082949]
[   26.082949] 3 locks held by kworker/57:1/414:
[   26.082950]  #0: ff11000ffddfdc60 (&rq->__lock){-.-.}-{2:2}, at: raw_spin_rq_lock_nested+0x53/0xa0
[   26.082953]  #1: ffffffff86871460 (console_lock){+.+.}-{0:0}, at: vprintk_emit+0x144/0x1c0
[   26.082956]  #2: ffffffff868714b8 (console_srcu){....}-{0:0}, at: console_flush_one_record+0x7c/0x330
[   26.082959]
[   26.082959] stack backtrace:
[   26.082960] CPU: 57 UID: 0 PID: 414 Comm: kworker/57:1 Not tainted 7.1.0-rc2-00057-gb3a2dfa8b42e #44 PREEMPT(lazy)
[   26.082962] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
[   26.082963] Workqueue:  0x0 (mm_percpu_wq)
[   26.082966] Call Trace:
[   26.082967]  <TASK>
[   26.082969]  dump_stack_lvl+0x78/0xe0
[   26.082973]  print_circular_bug+0xd5/0xf0
[   26.082976]  check_noncircular+0x14a/0x160
[   26.082979]  ? save_trace+0x56/0x170
[   26.082983]  check_prev_add+0xf1/0xc50
[   26.082987]  validate_chain+0x5c5/0x6f0
[   26.082990]  __lock_acquire+0x6e5/0xc70
[   26.082993]  lock_acquire+0xc7/0x2d0
[   26.082996]  ? console_lock_spinning_enable+0x40/0x70
[   26.082997]  ? __lock_release+0x15b/0x2a0
[   26.082999]  ? console_lock_spinning_enable+0x39/0x70
[   26.083001]  console_lock_spinning_enable+0x5c/0x70
[   26.083003]  ? console_lock_spinning_enable+0x40/0x70
[   26.083004]  console_emit_next_record+0xcf/0x200
[   26.083007]  console_flush_one_record+0x223/0x330
[   26.083010]  console_unlock+0x6d/0x130
[   26.083011]  ? vprintk_emit+0x144/0x1c0
[   26.083014]  vprintk_emit+0x187/0x1c0
[   26.083016]  ? hrtick_start_fair+0x88/0xa0
[   26.083018]  _printk+0x5b/0x80
[   26.083022]  __report_bug+0xf3/0x1f0
[   26.083025]  ? lock_acquire+0xc7/0x2d0
[   26.083028]  ? raw_spin_rq_lock_nested+0x53/0xa0
[   26.083029]  ? hrtick_start_fair+0x88/0xa0
[   26.083031]  report_bug+0x2c/0x80
[   26.083034]  handle_bug+0x214/0x250
[   26.083036]  exc_invalid_op+0x17/0x70
[   26.083037]  asm_exc_invalid_op+0x1a/0x20
[   26.083039] RIP: 0010:hrtick_start_fair+0x88/0xa0
[   26.083041] Code: 29 d0 31 d2 48 89 c6 b8 00 00 10 00 48 f7 f6 48 0f af c1 48 c1 e8 0a 48 89 c6 e9 03 57 ff ff 48 3b 77 18 74 09 e9 58 e8 ba 00 <0f> 0b eb 90 e9 bf 58 ff ff 66 66 2e 0f 1f 84 00 00 00 00 00 0f 1f
[   26.083042] RSP: 0000:ffa00000022dfda0 EFLAGS: 00010006
[   26.083044] RAX: ff11000ffddfdc00 RBX: ff11000103ba0000 RCX: 0000000000000000
[   26.083045] RDX: 0000000000000038 RSI: ff11000103ba0000 RDI: ff11000ffe1fdc00
[   26.083046] RBP: 0000000000000001 R08: 0000000000000001 R09: 0000000000000014
[   26.083047] R10: 0000000000000001 R11: ff11000ffe1fdd48 R12: ff11000ffe1fdc00
[   26.083047] R13: ff11000103ba00c8 R14: ff110001098080c8 R15: ff11000ffe1fec30
[   26.083051]  __set_next_task_fair+0x1de/0x210
[   26.083054]  pick_next_task+0x6fc/0x9c0
[   26.083058]  __schedule+0x1a8/0x7d0
[   26.083061]  schedule+0x3a/0xe0
[   26.083063]  worker_thread+0xd0/0x360
[   26.083065]  ? __pfx_worker_thread+0x10/0x10
[   26.083068]  kthread+0xf4/0x130
[   26.083069]  ? __pfx_kthread+0x10/0x10
[   26.083071]  ret_from_fork+0x29f/0x330
[   26.083073]  ? __pfx_kthread+0x10/0x10
[   26.083074]  ret_from_fork_asm+0x1a/0x30
[   26.083079]  </TASK>
[   26.234402] WARNING: kernel/sched/fair.c:7617 at hrtick_start_fair+0x88/0xa0, CPU#57: kworker/57:1/414
[   26.235937] Modules linked in:
[   26.236462] CPU: 57 UID: 0 PID: 414 Comm: kworker/57:1 Not tainted 7.1.0-rc2-00057-gb3a2dfa8b42e #44 PREEMPT(lazy)
[   26.238175] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
[   26.239744] Workqueue:  0x0 (mm_percpu_wq)
[   26.240434] RIP: 0010:hrtick_start_fair+0x88/0xa0
[   26.241225] Code: 29 d0 31 d2 48 89 c6 b8 00 00 10 00 48 f7 f6 48 0f af c1 48 c1 e8 0a 48 89 c6 e9 03 57 ff ff 48 3b 77 18 74 09 e9 58 e8 ba 00 <0f> 0b eb 90 e9 bf 58 ff ff 66 66 2e 0f 1f 84 00 00 00 00 00 0f 1f
[   26.244282] RSP: 0000:ffa00000022dfda0 EFLAGS: 00010006
[   26.245154] RAX: ff11000ffddfdc00 RBX: ff11000103ba0000 RCX: 0000000000000000
[   26.246338] RDX: 0000000000000038 RSI: ff11000103ba0000 RDI: ff11000ffe1fdc00
[   26.247523] RBP: 0000000000000001 R08: 0000000000000001 R09: 0000000000000014
[   26.248706] R10: 0000000000000001 R11: ff11000ffe1fdd48 R12: ff11000ffe1fdc00
[   26.249890] R13: ff11000103ba00c8 R14: ff110001098080c8 R15: ff11000ffe1fec30
[   26.251078] FS:  0000000000000000(0000) GS:ff11001076d9c000(0000) knlGS:0000000000000000
[   26.252413] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   26.253374] CR2: 00007fcf1a265dc0 CR3: 000000017d5d5005 CR4: 0000000000371ef0
[   26.254561] Call Trace:
[   26.254983]  <TASK>
[   26.255350]  __set_next_task_fair+0x1de/0x210
[   26.256088]  pick_next_task+0x6fc/0x9c0
[   26.256737]  __schedule+0x1a8/0x7d0
[   26.257330]  schedule+0x3a/0xe0
[   26.257869]  worker_thread+0xd0/0x360
[   26.258492]  ? __pfx_worker_thread+0x10/0x10
[   26.259214]  kthread+0xf4/0x130
[   26.259751]  ? __pfx_kthread+0x10/0x10
[   26.260386]  ret_from_fork+0x29f/0x330
[   26.261020]  ? __pfx_kthread+0x10/0x10
[   26.261656]  ret_from_fork_asm+0x1a/0x30
[   26.262321]  </TASK>
[   26.262703] irq event stamp: 1022
[   26.263269] hardirqs last  enabled at (1021): [<ffffffff81eb3cf8>] _raw_spin_unlock_irq+0x28/0x50
[   26.264735] hardirqs last disabled at (1022): [<ffffffff81ea7b5e>] __schedule+0x6be/0x7d0
[   26.266087] softirqs last  enabled at (0): [<ffffffff812a1631>] copy_process+0xa91/0x1bd0
[   26.267436] softirqs last disabled at (0): [<0000000000000000>] 0x0
[   26.268478] ---[ end trace 0000000000000000 ]---
[   26.269297] ------------[ cut here ]------------
[   26.270125] WARNING: kernel/sched/fair.c:6316 at set_next_entity+0x22a/0x290, CPU#56: swapper/56/0
[   26.271635] Modules linked in:
[   26.272169] CPU: 56 UID: 0 PID: 0 Comm: swapper/56 Tainted: G        W           7.1.0-rc2-00057-gb3a2dfa8b42e #44 PREEMPT(lazy)
[   26.274099] Tainted: [W]=WARN
[   26.274617] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
[   26.276211] RIP: 0010:set_next_entity+0x22a/0x290
[   26.277008] Code: 74 71 48 83 bb 40 01 00 00 00 48 8d 93 40 01 00 00 0f 84 ec fe ff ff 31 f6 48 8b bd 78 01 00 00 e8 6b 04 05 00 e9 d9 fe ff ff <0f> 0b e9 57 fe ff ff 48 c1 e0 14 31 d2 48 f7 f7 e9 5a ff ff ff 48
[   26.280106] RSP: 0018:ffa0000000267e00 EFLAGS: 00010082
[   26.280989] RAX: 00000006127857f5 RBX: ff11000103ba0080 RCX: 00000000001aa2dd
[   26.282176] RDX: 0000000000000000 RSI: ff11000103ba0080 RDI: 00000006127857f5
[   26.283368] RBP: ff1100016d2f4000 R08: ff11000ffddfefc0 R09: ff11000101462f80
[   26.284561] R10: 0000000000000001 R11: 0000000000000000 R12: ff11000ffddfdc00
[   26.285751] R13: ff11000103ba0000 R14: ff11000ffddfdc00 R15: 0000000000000000
[   26.286944] FS:  0000000000000000(0000) GS:ff1100107699c000(0000) knlGS:0000000000000000
[   26.288289] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   26.289252] CR2: 000055c32c010520 CR3: 000000000303e003 CR4: 0000000000371ef0
[   26.290443] Call Trace:
[   26.290870]  <TASK>
[   26.291242]  set_next_task_fair+0x39/0x80
[   26.291927]  pick_next_task+0x6fc/0x9c0
[   26.292581]  ? do_raw_spin_lock+0xae/0xc0
[   26.293263]  ? lock_acquired+0x125/0x160
[   26.293932]  __schedule+0x1a8/0x7d0
[   26.294533]  schedule_idle+0x23/0x40
[   26.295147]  cpu_startup_entry+0x29/0x30
[   26.295815]  start_secondary+0xf8/0x100
[   26.296466]  common_startup_64+0x12c/0x138
[   26.297165]  </TASK>
[   26.297550] irq event stamp: 4354
[   26.298119] hardirqs last  enabled at (4353): [<ffffffff813e6475>] tick_nohz_idle_exit+0x75/0x110
[   26.299597] hardirqs last disabled at (4354): [<ffffffff81ea7b5e>] __schedule+0x6be/0x7d0
[   26.300955] softirqs last  enabled at (4312): [<ffffffff812ae596>] handle_softirqs+0x366/0x440
[   26.302385] softirqs last disabled at (4307): [<ffffffff812ae796>] __irq_exit_rcu+0xb6/0x170
[   26.303789] ---[ end trace 0000000000000000 ]---
[   26.304587] psi: inconsistent task state! task=1305:nop cpu=56 psi_flags=14 clear=0 set=10
[   26.304592] BUG: unable to handle page fault for address: 00000000000012a0
[   26.307136] #PF: supervisor read access in kernel mode
[   26.308008] #PF: error_code(0x0000) - not-present page
[   26.308881] PGD 16e83d067 P4D 17295a067 PUD 102449067 PMD 0
[   26.309834] Oops: Oops: 0000 [#1] SMP NOPTI
[   26.310541] CPU: 56 UID: 1000 PID: 1305 Comm: nop Tainted: G        W           7.1.0-rc2-00057-gb3a2dfa8b42e #44 PREEMPT(lazy)
[   26.312449] Tainted: [W]=WARN
[   26.312964] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
[   26.314544] RIP: 0010:__schedule+0xa0/0x7d0
[   26.315252] Code: fa f6 c4 02 0f 85 39 06 00 00 44 89 f7 e8 98 5e 50 ff 8b bb 28 10 00 00 48 89 ee e8 ca d0 45 ff 48 89 df 31 f6 e8 f0 39 45 ff <44> 8b b3 a0 12 00 00 48 8d 7b 48 45 85 f6 74 0b 48 8b 83 88 12 00
[   26.318334] RSP: 0018:ffa0000004963eb8 EFLAGS: 00010046
[   26.319212] RAX: ff11000101462f80 RBX: 0000000000000000 RCX: 0000000000000000
[   26.320404] RDX: 0000000000000000 RSI: ff11000103ba0000 RDI: 0000000000000000
[   26.321595] RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000001
[   26.322521] ------------[ cut here ]------------
[   26.322787] R10: ff11000ffdc18500 R11: 0000000000000000 R12: ff11000103ba0000
[   26.322788] R13: ff11000ffe1fdc00 R14: ffffffff812faf83 R15: 0000000000000000
[   26.323604] RCU not watching for tracepoint
[   26.324798] FS:  00007fcf1a107780(0000) GS:ff1100107699c000(0000) knlGS:0000000000000000
[   26.325969] WARNING: include/trace/events/sched.h:886 at __schedule+0x6af/0x7d0, CPU#11: nop/1312
[   26.326679] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   26.328024] Modules linked in:
[   26.329492] CR2: 00000000000012a0 CR3: 000000017d5d5005 CR4: 0000000000371ef0
[   26.330507]
[   26.331037] Call Trace:
[   26.332257] CPU: 11 UID: 1000 PID: 1312 Comm: nop Tainted: G        W           7.1.0-rc2-00057-gb3a2dfa8b42e #44 PREEMPT(lazy)
[   26.332529]  <TASK>
[   26.332960] Tainted: [W]=WARN
[   26.334872]  ? handle_softirqs+0x366/0x440
[   26.335246] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
[   26.335761]  schedule+0x3a/0xe0
[   26.336459] RIP: 0003:ktime_get_update_offsets_now+0x141/0x200
[   26.338045]  irqentry_exit+0x2e4/0x770
[   26.338589] RSP: cac0:7fffffffffffffff EFLAGS: 00000006
[   26.339569]  asm_sysvec_apic_timer_interrupt+0x1a/0x20
[   26.340211]  ORIG_RAX: 0000000615a347d5
[   26.341088] RIP: 0033:0x40110c
[   26.341957] RAX: ff11000ff25ecac0 RBX: ff11000ff25ecac0 RCX: ffffffff812fcaf0
[   26.342610] Code: 7a ff ff ff c6 05 17 2f 00 00 01 5d c3 90 c3 66 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 f3 0f 1e fa eb 8a 55 48 89 e5 f3 90 <eb> fc 00 00 f3 0f 1e fa 48 83 ec 08 48 83 c4 08 c3 00 00 00 00 00
[   26.343140] RDX: ffffffff813cc47a RSI: 0000000000000006 RDI: 0000000300000000
[   26.344337] RSP: 002b:00007ffc7959d830 EFLAGS: 00000246
[   26.347426] RBP: ffa000000499be60 R08: ff11000ff25ecac0 R09: ff11000ff25fed80
[   26.348613]
[   26.349493] R10: ffffffff812fcb29 R11: ff11000ff25fdc00 R12: ff11000ff25fed80
[   26.350688] RAX: 00007fcf1a2fae28 RBX: 0000000000000000 RCX: 0000000000403e40
[   26.350964] R13: ffffffff812faf83 R14: 0000000000000000 R15: ff11000ff25fdc00
[   26.352158] RDX: 00007ffc7959d968 RSI: 00007ffc7959d958 RDI: 0000000000000001
[   26.353355] FS:  00007fb34f06e780 GS:  0000000000000000
[   26.354548] RBP: 00007ffc7959d830 R08: 00007fcf1a2f3680 R09: 00007fcf1a2f4fe0
[   26.355742] irq event stamp: 1201
[   26.356620] R10: 00007ffc7959d570 R11: 0000000000000203 R12: 00007ffc7959d958
[   26.357817] hardirqs last  enabled at (1201): [<ffffffff8100148a>] asm_sysvec_apic_timer_interrupt+0x1a/0x20
[   26.358389] R13: 0000000000000001 R14: 00007fcf1a345000 R15: 0000000000403e40
[   26.359586] hardirqs last disabled at (1199): [<ffffffff812ae626>] handle_softirqs+0x3f6/0x440
[   26.361223]  </TASK>
[   26.362416] softirqs last  enabled at (1200): [<ffffffff812ae596>] handle_softirqs+0x366/0x440
[   26.363847] Modules linked in:
[   26.364235] softirqs last disabled at (1195): [<ffffffff812ae796>] __irq_exit_rcu+0xb6/0x170
[   26.365667]
[   26.366198] ---[ end trace 0000000000000000 ]---
[   26.367607] CR2: 00000000000012a0
[   26.369237] ---[ end trace 0000000000000000 ]---
[   26.369245] kernel tried to execute NX-protected page - exploit attempt? (uid: 1000)
[   26.370018] RIP: 0010:__schedule+0xa0/0x7d0
[   26.371323] BUG: unable to handle page fault for address: ff1100103fdc6a40
[   26.372029] Code: fa f6 c4 02 0f 85 39 06 00 00 44 89 f7 e8 98 5e 50 ff 8b bb 28 10 00 00 48 89 ee e8 ca d0 45 ff 48 89 df 31 f6 e8 f0 39 45 ff <44> 8b b3 a0 12 00 00 48 8d 7b 48 45 85 f6 74 0b 48 8b 83 88 12 00
[   26.373188] #PF: supervisor instruction fetch in kernel mode
[   26.376272] RSP: 0018:ffa0000004963eb8 EFLAGS: 00010046
[   26.377227] #PF: error_code(0x0011) - permissions violation
[   26.378104] RAX: ff11000101462f80 RBX: 0000000000000000 RCX: 0000000000000000
[   26.379043] PGD 908e067
[   26.380235] RDX: 0000000000000000 RSI: ff11000103ba0000 RDI: 0000000000000000
[   26.380236] P4D 908f067 PUD 80000010000001e3
[   26.380677] RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000001
[   26.381873]
[   26.382617] R10: ff11000ffdc18500 R11: 0000000000000000 R12: ff11000103ba0000
[   26.383814] Oops: Oops: 0011 [#2] SMP NOPTI
[   26.384088] R13: ff11000ffe1fdc00 R14: ffffffff812faf83 R15: 0000000000000000
[   26.385283] CPU: 11 UID: 1000 PID: 1312 Comm: nop Tainted: G      D W           7.1.0-rc2-00057-gb3a2dfa8b42e #44 PREEMPT(lazy)
[   26.385993] FS:  00007fcf1a107780(0000) GS:ff1100107699c000(0000) knlGS:0000000000000000
[   26.387187] Tainted: [D]=DIE, [W]=WARN
[   26.389100] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   26.390448] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
[   26.391088] CR2: 00000000000012a0 CR3: 000000017d5d5005 CR4: 0000000000371ef0
[   26.392055] RIP: 0010:0xff1100103fdc6a40
[   26.393640] Kernel panic - not syncing: Fatal exception
[   27.473979] Shutting down cpus with NMI
[   27.476542] Kernel Offset: disabled
[   27.477157] Rebooting in 5 seconds..
QEMU: Terminated


^ permalink raw reply related

* Re: [PATCH 1/1] mm/thp: clear deferred split shrinker bits when queues drain
From: David Hildenbrand (Arm) @ 2026-06-03  8:02 UTC (permalink / raw)
  To: Lance Yang, Andrew Morton
  Cc: ljs, shakeel.butt, mhocko, david, roman.gushchin, muchun.song,
	qi.zheng, yosry.ahmed, ziy, liam, usama.arif, kas, vbabka, ryncsn,
	zaslonko, gor, wangkefeng.wang, baolin.wang, baohua, dev.jain,
	npache, ryan.roberts, cgroups, linux-mm, linux-kernel,
	Johannes Weiner
In-Reply-To: <f5061a2f-c52a-47c4-855c-82f3967833d6@linux.dev>

On 6/3/26 04:00, Lance Yang wrote:
> 
> 
> On 2026/6/3 04:37, Andrew Morton wrote:
>> On Tue,  2 Jun 2026 12:34:53 +0800 Lance Yang <lance.yang@linux.dev> wrote:
>>
>>> From: Lance Yang <lance.yang@linux.dev>
>>>
>>> deferred_split_count() returns the raw list_lru count. When the per-memcg,
>>> per-node list is empty, that count is 0.
>>>
>>> That skips scanning, but it does not tell memcg reclaim that the shrinker
>>> is empty. shrink_slab_memcg() only clears the memcg shrinker bit when the
>>> count callback reports SHRINK_EMPTY.
>>>
>>> Return SHRINK_EMPTY for an empty deferred split list, so the bit can be
>>> cleared once the queue has drained.
>>>
>>> Signed-off-by: Lance Yang <lance.yang@linux.dev>
>>> ---
>>>   mm/huge_memory.c | 5 ++++-
>>>   1 file changed, 4 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/mm/huge_memory.c b/mm/huge_memory.c
>>> index 72f6caf0fec6..62d598290c3b 100644
>>> --- a/mm/huge_memory.c
>>> +++ b/mm/huge_memory.c
>>> @@ -4397,7 +4397,10 @@ void deferred_split_folio(struct folio *folio, bool
>>> partially_mapped)
>>>   static unsigned long deferred_split_count(struct shrinker *shrink,
>>>           struct shrink_control *sc)
>>>   {
>>> -    return list_lru_shrink_count(&deferred_split_lru, sc);
>>> +    unsigned long count;
>>> +
>>> +    count = list_lru_shrink_count(&deferred_split_lru, sc);
>>> +    return count ?: SHRINK_EMPTY;
>>>   }
>>>     static bool thp_underused(struct folio *folio)
>>
>> Should this be handled as a fix against hannes's "mm: switch deferred
>> split shrinker to list_lru"?
> 
> Hmm ... I noticed this while looking at Johannes' work, but the
> behavior is older than that ...
> 
> We also discussed the Fixes tag earlier[1] and decided to leave it
> out. There is no missed reclaim, only some extra reclaim work :)

Right, I conclude that this can be a separate patch on top.

-- 
Cheers,

David

^ permalink raw reply

* Re: [LSF/MM/BPF TOPIC][RFC PATCH v4 00/27] Private Memory Nodes (w/ Compressed RAM)
From: Gregory Price @ 2026-06-03  7:02 UTC (permalink / raw)
  To: Balbir Singh
  Cc: lsf-pc, linux-kernel, linux-cxl, cgroups, linux-mm,
	linux-trace-kernel, damon, kernel-team, gregkh, rafael, dakr,
	dave, jonathan.cameron, dave.jiang, alison.schofield,
	vishal.l.verma, ira.weiny, dan.j.williams, longman, akpm, david,
	lorenzo.stoakes, Liam.Howlett, vbabka, rppt, surenb, mhocko,
	osalvador, ziy, matthew.brost, joshua.hahnjy, rakie.kim,
	byungchul, ying.huang, apopple, axelrasmussen, yuanchu, weixugc,
	yury.norov, linux, mhiramat, mathieu.desnoyers, tj, hannes,
	mkoutny, jackmanb, sj, baolin.wang, npache, ryan.roberts,
	dev.jain, baohua, lance.yang, muchun.song, xu.xin16,
	chengming.zhou, jannh, linmiaohe, nao.horiguchi, pfalcato,
	rientjes, shakeel.butt, riel, harry.yoo, cl, roman.gushchin,
	chrisl, kasong, shikemeng, nphamcs, bhe, zhengqi.arch,
	terry.bowman
In-Reply-To: <ah-0CyZurn5D1ezY@parvat>

On Wed, Jun 03, 2026 at 03:00:01PM +1000, Balbir Singh wrote:
> On Tue, Jun 02, 2026 at 09:57:48AM +0100, Gregory Price wrote:
> > On Tue, Jun 02, 2026 at 12:16:50PM +1000, Balbir Singh wrote:
> > > 
> > > I was think we wouldn't need explicit flags and that allocations would
> > > happen from user space using __GFP_THISNODE to the node or via a nodemask
> > > based on nodes of interest. Is there a reason to add this flag, a system
> > > might have more than one source of N_MEMORY_PRIVATE?
> > > 
> > 
> > There's a few things to unpack here.  I discussed this many times on
> > list and at LSF, but to reiterate.
> > 
> > 1) __GFP_THISNODE is insufficient to enforce isolation and otherwise
> >    not particularly useful.  Additionally, from userland, it's not
> >    something you can actually set.
> 
> I was thinking mbind()/mempolicy() is how we get to it. It already
> accepts a nodemask.
>

First let me say:  I want to enable mbind access to these nodes.

But let me caveat:  I think that needs more time to develop, and
in the meantime, we can enable the /dev/xxx pattern somewhat trivially.

First let me address a few things about mbind/mempolicy and how it
interacts with page_alloc.c, I gave this overview at LSF but I don't
remember if I posted it in any of my follow ups.


1) Fallback lists are filtered by nodemask, the nodemask does not replace
   the fallback list.

Here is how the page allocator fallback lists and nodemasks interact:

   Fallbacks A:  A B 
   Fallbacks B:  B A
   Fallbacks C:  C A B   (Private)
   Fallbacks D:  D B A   (Private)

Lets say you pass:

   alloc_pages_node(C, ..., nodemask(A,C,D))

So we get

  Fallback(C,A,B) & nodemask(A,C,D) -> iterate(C,A)

If we wanted to change this behavior, realistically we'd be looking for
a way to add specific nodes to certain fallback lists - rather than
modify the nodemask interaction in some way.

I think this is out of scope for the first iteration - so supporting
anything other than mbind() from the start is just pointless.

The only feasible mempolicy you can apply is single-node bind, so
realistically you can only support mbind.


2) full mempolicy support doesn't really make sense

   task mempolicy PROBABLY should never really touch private nodes,
   while VMA policy certainly can.  Assuming we're able to support
   multi-private-node masks, none of the non-bind mempolicies even
   make sense for most private nodes (interleave? weighted interleave?)

   I haven't worked through all the implications of a task policy having
   a private node attached, but the longer I think about it, the less it
   makes sense to just support this outright.


3) Introducing mbind support is not just a simple nodemask on a VMA,
   It also implies migration, cgroup/cpuset, and UAPI interactions.

   a) migration:
      
      mbind/mempolicy can and will engage migration when it is called
      with certain flags.  Migration has subtle LRU interactions, but
      the patch set I have at least allows this to work.

   b) cgroup/cpuset:
   
      cpuset.mems rebinding will cause private nodes to be quietly
      rebound to non-private nodes within a nodemask.

   c) between A and B - we really want MPOL_F_STATIC to be required
      for mbind to be applied to private node so that it is never
      forcefully remapped.

      That's a UAPI semantic change specific for private nodes we
      should really take time to consider.


4) File VMA interactions don't entirely make sense with mbind

   In theory you might want:

   fd = open("somefile", ...);
   mem = mmap(fd, ...);
   mbind(mem, ..., private_node);
   for page in mem:
      mem[page_off] /* fault file into private memory */

   In reality: This does not work the way you want.

   I went digging and we need a few mild extensions to allow
   migration on mbind to work for pagecache pages, and the fault
   path does not necessarily respect the vma mempolicy always.

   You also start getting into the question of "what happens when
   the node is out of memory and you don't have reclaim support?".
   The OOM implications jump out at you pretty aggressively.

   Moreover other tasks can force the page cache pages to be moved
   as well.  So the programming model here just kind of sucks.

   Works great for anon memory though :]

For all these reasons, I think the be mbind/mempolicy support with
private nodes needs to be brought in with follow up work - not
introduced as part of the baseline set.

> > 
> >    for node in possible_nodes:
> >        alloc_pages_node(private_node, __GFP_THISNODE)
> > 
> >    In fact it's the opposite semantic of what we want.
> >    THISNODE says: "Do not fallback back to OTHER nodes".
> > 
> 
> That's why we need to control the fallback nodes carefully for
> N_MEMORY_PRIVATE
>

My point is that __GFP_THISNODE is not actually useful.

If we go by nodemask, submitting a single-node nodemask is the
equivalent of an empty fallback list.

If we gate access to a private node by __GFP_THISNODE... this is the
same as just providing a single-node nodelist (putting aside the OOM
implications for a moment).

And it doesn't even buy you any new filtering ability against existing
nodemask iterators that may already utilize __GFP_THISNODE.  i.e.

   for node in online_nodes:
       alloc_pages_node(node, __GFP_THISNODE, ...)
       /* Alloc per-node resources */

   This pattern is undesirable, but completely valid.

So overloading/requiring __GFP_THISNODE is just not useful.

I will follow up soon with a new version that limits the private node
interface to just nodemask and fallback list controls.

I need to test a few more things related to removing normal nodes from
private node fallbacks before I feel comfortable shipping without
__GFP_PRIVATE.

> >    The semantic we want is "Do not allow allocations from private
> >    nodes UNLESS we specifically request" (__GFP_PRIVATE).
> > 
> >    __GFP_THISNODE does not actually buy you anything here, AND it's
> >    worse, in the scenario where a private node makes its way into the
> >    preferred slot (via possible_nodes or some other nodemask), the
> >    allocator cannot fall back to a node it can access.
> > 
> >    __GFP_THISNODE cannot be overloaded to do anything useful here.
> 
> Let me clarify, I meant to say, let's use a nodemask for allocation
> and __GFP_THISNODE gets us to the node we desire, if that is the only
> node. My earlier comment might not have been clear.
>

My point was that __GFP_THISNODE is pointless and reduces to providing a
single node nodemask anyway.

The contention over __GFP_PRIVATE is a bit ideological - do we want:

  1) A hard guarantee that allocations to a private node are controlled
     (__GFP_PRIVATE implies the caller knows what it's doing)

  or

  2) A soft guarantee (fallback list isolation only), and needing to
     deal with undesired behavior that's "not technically a bug"
     associated with existing users of global nodemasks (possible,
     online, etc).

I am arguing for #1 - the community has argued for #2 and "fixing
existing nodemask users".  I think we can ship #2 and pivot to #1 if we
find fixing existing users is infeasible or too much of a maintenance
burden.

> 
> Why not use mbind() API's? Do we want to gate allocation/privileges
> via a /dev?
>

We want to eventually enable it, but we really need to treat these
extensions as a separate step from the base so that the UAPI
implications are given proper scrutiny.

In the short term, /dev/xxx and driver-local/service-local control
of a node is still very useful.

For example, for my compressed memory work, I have found that if
implemented as a swap backend - the kernel can manage the node without
any UAPI implications at all :].

A driver managing memory on a private node could do the same.

~Gregory

^ permalink raw reply

* Re: [LSF/MM/BPF TOPIC][RFC PATCH v4 00/27] Private Memory Nodes (w/ Compressed RAM)
From: Balbir Singh @ 2026-06-03  5:00 UTC (permalink / raw)
  To: Gregory Price
  Cc: lsf-pc, linux-kernel, linux-cxl, cgroups, linux-mm,
	linux-trace-kernel, damon, kernel-team, gregkh, rafael, dakr,
	dave, jonathan.cameron, dave.jiang, alison.schofield,
	vishal.l.verma, ira.weiny, dan.j.williams, longman, akpm, david,
	lorenzo.stoakes, Liam.Howlett, vbabka, rppt, surenb, mhocko,
	osalvador, ziy, matthew.brost, joshua.hahnjy, rakie.kim,
	byungchul, ying.huang, apopple, axelrasmussen, yuanchu, weixugc,
	yury.norov, linux, mhiramat, mathieu.desnoyers, tj, hannes,
	mkoutny, jackmanb, sj, baolin.wang, npache, ryan.roberts,
	dev.jain, baohua, lance.yang, muchun.song, xu.xin16,
	chengming.zhou, jannh, linmiaohe, nao.horiguchi, pfalcato,
	rientjes, shakeel.butt, riel, harry.yoo, cl, roman.gushchin,
	chrisl, kasong, shikemeng, nphamcs, bhe, zhengqi.arch,
	terry.bowman
In-Reply-To: <ah6bDNxlB1zBUnzN@gourry-fedora-PF4VCD3F>

On Tue, Jun 02, 2026 at 09:57:48AM +0100, Gregory Price wrote:
> On Tue, Jun 02, 2026 at 12:16:50PM +1000, Balbir Singh wrote:
> > On Sun, May 24, 2026 at 09:50:06PM -0400, Gregory Price wrote:
> > > 
> > > I'm debating on whether to include OPS_MEMPOLICY in the initial version
> > > if only because it's not intuitive how it interacts with pagecache. That
> > > needs more time to bake.
> > >
> > 
> > It makes sense to look at it and then decide if it makes sense.
> >
> 
> I am thinking i will ship without any OPS flags at all for now and the
> have the introduction of ops as a separate series.
> 
> > > alloc_pages_node() is the kernel interface
> > 
> > I was think we wouldn't need explicit flags and that allocations would
> > happen from user space using __GFP_THISNODE to the node or via a nodemask
> > based on nodes of interest. Is there a reason to add this flag, a system
> > might have more than one source of N_MEMORY_PRIVATE?
> > 
> 
> There's a few things to unpack here.  I discussed this many times on
> list and at LSF, but to reiterate.
> 
> 1) __GFP_THISNODE is insufficient to enforce isolation and otherwise
>    not particularly useful.  Additionally, from userland, it's not
>    something you can actually set.

I was thinking mbind()/mempolicy() is how we get to it. It already
accepts a nodemask.

> 
>    for node in possible_nodes:
>        alloc_pages_node(private_node, __GFP_THISNODE)
> 
>    In fact it's the opposite semantic of what we want.
>    THISNODE says: "Do not fallback back to OTHER nodes".
> 

That's why we need to control the fallback nodes carefully for
N_MEMORY_PRIVATE

>    The semantic we want is "Do not allow allocations from private
>    nodes UNLESS we specifically request" (__GFP_PRIVATE).
> 
>    __GFP_THISNODE does not actually buy you anything here, AND it's
>    worse, in the scenario where a private node makes its way into the
>    preferred slot (via possible_nodes or some other nodemask), the
>    allocator cannot fall back to a node it can access.
> 
>    __GFP_THISNODE cannot be overloaded to do anything useful here.

Let me clarify, I meant to say, let's use a nodemask for allocation
and __GFP_THISNODE gets us to the node we desire, if that is the only
node. My earlier comment might not have been clear.

> 
> 2) We're trying not to expose *ANY* userland APIs for this, at all.
> 
>    The ultimate goal here should be one of two things:
> 
>    1) fd = open(/dev/xxx, ...);
>       mem = mmap(fd, ...);
>       mem[0] = 0xDEADBEEF; /* Fault device page into page table */
> 
>       In this case, the driver is responsible for doing the
>       alloc_pages_node() call.
> 
>    or
> 
>    2) mem = mmap(NULL, ..., ANON);
>       mbind(mem, ..., private_node);
>       mem[0] = 0xDEADBEEF; /* Fault device page into page table */
> 
>       in this case mempolicy.c is responsible for doing the
>       alloc_pages_node() call via the _mpol() alloc variants.
> 
> Addition OPT flags (reclaim, compaction, whatever), would
> (optionally) allow mm/ to operate on the device memory with, for
> example, mmu_notifier callbacks to tell the device to invalidate
> whatever it's caching about that page.
> 
> This would all be relatively transparent the userland, all userland
> "knows" is that it's getting memory from a device (/dev/xxx) or a
> node it's otherwise aware of hosting device memory somehow.
> 

Why not use mbind() API's? Do we want to gate allocation/privileges
via a /dev?

Balbir

^ permalink raw reply

* Re: [PATCH v5 0/9] mm: switch THP shrinker to list_lru
From: Lance Yang @ 2026-06-03  4:44 UTC (permalink / raw)
  To: hannes
  Cc: lance.yang, akpm, david, ljs, shakeel.butt, mhocko, david,
	roman.gushchin, muchun.song, qi.zheng, yosry.ahmed, ziy, liam,
	usama.arif, kas, vbabka, ryncsn, zaslonko, gor, baolin.wang,
	baohua, dev.jain, npache, ryan.roberts, cgroups, linux-mm,
	linux-kernel
In-Reply-To: <ah9PGv12mqai84ES@cmpxchg.org>


On Tue, Jun 02, 2026 at 05:46:02PM -0400, Johannes Weiner wrote:
>On Mon, Jun 01, 2026 at 04:36:52PM +0800, Lance Yang wrote:
>> As the changelog above says, the old queue is per-memcg only, rather
>> than per-memcg-per-node. So reclaim on one node can still walk the whole
>> memcg queue and split underused THPs from other nodes in the same memcg.
>> 
>> But I think the new one can lose reclaim in the cgroup.memory=nokmem
>> case ...
>> 
>> With nokmem, the deferred shrinker can still run from memcg reclaim,
>> because it is SHRINKER_NONSLAB. But the list_lru is no longer per-memcg:
>> 
>> __list_lru_init() clears memcg_aware,
>> 
>> 	if (mem_cgroup_kmem_disabled())
>> 		memcg_aware = false;
>> 
>> so list_lru_from_memcg_idx() falls back to the shared node list:
>> 
>> static inline struct list_lru_one *
>> list_lru_from_memcg_idx(struct list_lru *lru, int nid, int idx)
>> {
>> 	if (list_lru_memcg_aware(lru) && idx >= 0) {
>> [...]
>> 	}
>> 	return &lru->node[nid].lru;
>> }
>> 
>> That makes the shrinker bit unreliable. __list_lru_add() still sets the
>> bit on the memcg passed in, but only when the list goes from empty to
>> non-empty:
>> 
>> bool __list_lru_add(struct list_lru *lru, struct list_lru_one *l,
>> 		    struct list_head *item, int nid,
>> 		    struct mem_cgroup *memcg)
>> {
>> 	if (list_empty(item)) {
>> [...]
>> 		if (!l->nr_items++)
>> 			set_shrinker_bit(memcg, nid, lru_shrinker_id(lru));
>> [...]
>> 		return true;
>> 	}
>> 	return false;
>> }
>> 
>> If memcg A adds the first folio, A gets the bit. If memcg B later adds a
>> folio to the same shared list, B does not get a bit, because the list
>> was already non-empty.
>> 
>> So in the A-first/B-later case, reclaim from B may not call the deferred
>> shrinker at all. The shared list is scanned from memcg reclaim only if
>> reclaim runs from the memcg that has the bit, such as A here, or from
>> global reclaim :)
>> 
>> Anyway, only after the shared list is emptied does the next memcg to add
>> a folio get to be the one with the bit, IIUC :)
>
>Sorry for the delay, this took me a bit to think about. The shrinker
>code is a mess.
>
>I read it the same way you do. And this is true for all list_lru users
>when nokmem is set: we just set random nonsense shrinker bits.
>
>HOWEVER, the generic shrinker code fixes that up by IGNORING random
>shrinker bits like this when !memcg_kmem_online(). And shrinking
>correctly happens only against the shared root queue when the reclaim
>iterator walks root_mem_cgroup.
>
>HOWEVER, the THP shrinker explicitly sets SHRINKER_NONSLAB, which in
>turn overrides the previous override. So yes there is a weirdness: we
>get the root cgroup invocation against the shared queue, and then one
>more time triggered by that random memcg bit.
>
>The most direct fix is to just drop SHRINKER_NONSLAB. It declares
>independence from kmem, which is no longer true.
>
>Cleaning up the shrinker code is left for another day.

Thanks for working on this!

Wondering if this fix trades one problem for another, though ...

Before this series, the deferred split shrinker had a real per-memcg
queue. Even with cgroup.memory=nokmem, memcg reclaim could still scan
that memcg's own deferred_split_queue:

memcg reclaim -> deferred split shrinker -> sc->memcg->deferred_split_queue

With the fix, nokmem + w/o SHRINKER_NONSLAB falls back to a
non-memcg-aware shrinker:

memcg reclaim -> skip deferred split shrinker

root/global reclaim -> deferred split shrinker -> shared list_lru

Is that expected? There woud be no memcg-driven deferred split reclaim
under nokmem, IIUC ...

Not sure what the right fix is, as I am not a memcg expert ...

Cheers, Lance

>Andrew, if there are no objections, can you please fold this?
>
>---
>
>>From 6787efabb9584824c196bf01c517d93aae3764c3 Mon Sep 17 00:00:00 2001
>From: Johannes Weiner <hannes@cmpxchg.org>
>Date: Tue, 2 Jun 2026 17:11:46 -0400
>Subject: [PATCH] mm: switch deferred split shrinker to list_lru fix
>
>Lance Yang points out a weirdness in the list_lru code with
>cgroup.memory=nokmem: in this mode, list_lru collapses to a shared
>per-node list that holds the folios, but __list_lru_add() still sets
>the shrinker bit on the owning memcg.
>
>Usually this is fine, because the generic shrinker code ignores these
>random bits when !memcg_kmem_online(). But the THP shrinker still has
>the SHRINKER_NONSLAB flag set, which specifically declares an
>independence from kmem. As a result, the shrinker fires twice per
>reclaim cycle: one during the regular root cgroup scan, and then one
>more time triggered from whichever memcg got the shrinker bit.
>
>Drop the flag, since it's no longer true. The deferred_split shrinker
>then behaves like every other list_lru-backed shrinker under nokmem,
>including the non-kmem ones (zswap, workingset shadow_nodes): skipped
>from memcg-internal reclaim, driven by global reclaim only.
>
>This needs proper cleaning up on the shrinker and list_lru side, but
>that's scope for a follow-up series. Just make it consistent now.
>
>Reported-by: Lance Yang <lance.yang@linux.dev>
>Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
>---
> mm/huge_memory.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
>diff --git a/mm/huge_memory.c b/mm/huge_memory.c
>index 72f6caf0fec6..aef495891f8c 100644
>--- a/mm/huge_memory.c
>+++ b/mm/huge_memory.c
>@@ -956,8 +956,7 @@ int folio_memcg_alloc_deferred(struct folio *folio)
> static int __init thp_shrinker_init(void)
> {
> 	deferred_split_shrinker = shrinker_alloc(SHRINKER_NUMA_AWARE |
>-						 SHRINKER_MEMCG_AWARE |
>-						 SHRINKER_NONSLAB,
>+						 SHRINKER_MEMCG_AWARE,
> 						 "thp-deferred_split");
> 	if (!deferred_split_shrinker)
> 		return -ENOMEM;
>-- 
>2.54.0
>
>

^ permalink raw reply

* Re: [PATCH v3 1/4] mm/zswap: Make shrink_worker writeback cursor per-memcg
From: Hao Jia @ 2026-06-03  3:02 UTC (permalink / raw)
  To: Yosry Ahmed
  Cc: akpm, tj, hannes, shakeel.butt, mhocko, mkoutny, nphamcs,
	chengming.zhou, muchun.song, roman.gushchin, cgroups, linux-mm,
	linux-kernel, linux-doc, Hao Jia
In-Reply-To: <ah9i3uhh3PFiS0Uk@google.com>



On 2026/6/3 07:19, Yosry Ahmed wrote:
>>>>>> Proactive writeback also wants a similar per-memcg cursor that is
>>>>>> scoped to the specified memcg, so that repeated invocations against
>>>>>> the same memcg make forward progress across its descendant memcgs
>>>>>> instead of restarting from the first child memcg each time.
>>>>>
>>>>> Is this a problem in practice?
>>>>>
>>>>> Is the concern the overhead of scanning memcgs repeatedly, or lack of
>>>>> fairness? I wonder if we should just do writeback in batches from all
>>>>> memcgs, similar to how reclaim does it, then evaluate at the end if we
>>>>> need to start over?
>>>>>
>>>>
>>>> Not using a per-cgroup cursor will cause issues for "repeated small-budget
>>>> calls" cases. For example, repeatedly triggering a 2MB writeback might
>>>> result in only writing back pages from the first few child memcgs every
>>>> time. In the worst-case scenario (where the writeback amount is less than
>>>> WB_BATCH), it might only ever write back from the first child memcg.
>>>
>>> Right, so a fairness concern?
>>>
>>> I wonder if we should just reclaim a batch from each memcg, then check
>>> if we reached the goal, otherwise start over. If the batch size is small
>>> enough that should work?
>>
>> Even with a small batch size, for small writeback requests triggered by
>> user-space (e.g., 2MB, which is batch size * N), it might still repeatedly
>> write back from only the first N child memcgs.
> 
> Yes, I understand, I am asking if this is a problem in practice. For
> this to be a problem we'd need to trigger small writeback requests and
> have many memcgs.
> 
>> This could cause the user-space agent to prematurely give up on zswap
>> writeback.
> 
> Why? The kernel should not return before trying to writeback from all
> memcgs. If we scan the first N child memcgs and did not writeback
> enough, we should keep going, right?
> 

Yes, this issue is not caused by the kernel, but rather by our 
user-space agent itself.

For instance, suppose a parent memcg has two children, memcg1 and 
memcg2, each with 200MB of zswap (100MB inactive). Triggering proactive 
writeback on the parent memcg will exhaust memcg1's inactive zswap 
pages. After that, even though memcg2 still has plenty of inactive zswap 
pages, it will continue to write back memcg1's active zswap pages. 
Writing back active zswap pages causes the user-space agent to 
prematurely abort the writeback because it detects that certain memcg 
metrics have exceeded predefined thresholds.

Of course, real-world scenarios are much more complex, and this kind of 
case is extremely rare in our environment.

That being said, your suggestion of using the global lock for the 
per-memcg cursors makes the writeback fairer and would resolve these 
corner cases.

>>> What if we do something like this (for the global cursor):
>>>
>>> 	do {
>>> 		memcg = xchg(zswap_next_shrink, NULL);
>>> 		memcg = mem_cgroup_iter(NULL, memcg, NULL);
>>> 		/* If the cursor was advanced from under us, try again */
>>> 		if (!try_cmpxchg(zswap_next_shrink, NULL, memcg))
>>> 			continue;
>>> 	} while (..);
>>> 			
>>>
>>
>> Regarding the code above, IIRC, both the global and per-cgroup cursors
>> suffer from race conditions. This race can cause mem_cgroup_iter(NULL, NULL,
>> NULL) to return the root memcg or its descendants, leading zswap to write
>> back pages from the wrong memcg.
> 
> Not the wrong memcg, it will just go back to the first memcg again,
> which should be fine as I mentioned below.
> 
>>
>> Additionally, since mem_cgroup_iter() puts the prev memcg ref and gets the
>> next memcg ref, a try_cmpxchg() failure on CPU1 might also lead to a ref
>> leak for memcg1.
>>
>>
>> 	CPU1                                       CPU2
>> memcg1 = xchg(pos, NULL)
>>                                 memcg2 = xchg(pos, NULL) memcg2 = NULL;
>>
>> memcg1 = mem_cgroup_iter()
>>                         mem_cgroup_iter(NULL, **NULL**, NULL) error memcg
>>                                  try_cmpxchg(pos,NULL,memcg2) succeed
>> try_cmpxchg(pos,NULL,memcg1) **fail**
> 
> Yes, we can probably just take a ref on the memcg before calling
> mem_cgroup_iter(). That being said, I think we can just keep the lock,
> see below.
> 
>>
>> I took a stab at implementing a cmpxchg()-based zswap_mem_cgroup_iter()
>> modeled after mem_cgroup_iter(), and it actually doesn't look that complex
>> after all :)
> 
> I don't think we should re-implement mem_cgroup_iter() here.
> 
> [..]
>>> There is a window where a racing shrinker will see the cursor as NULL
>>> and start over, but that should be fine. We can generalize this for the
>>> per-memcg cursor.
>>>
>>> That being said..
>>>
>>>>
>>>> Currently, this lock is only used in shrink_memcg(), proactive writeback,
>>>> and mem_cgroup_css_offline(). Note that shrink_memcg() only acquires the
>>>> lock of the root cgroup, and mem_cgroup_css_offline() is unlikely to be a
>>>> hot path.
>>>
>>> ..this made me realize it's probably fine to just use a global lock for
>>> now?
>>>
>>> IIUC the only additional contention to the existing lock will be from
>>> userspace proactive writeback, and that shouldn't be a big deal
>>> especially with the critical section being short?
>>>
>>
>> In the current patch implementation, this lock protects the cgroup's own
>> cursor variable. During each writeback, we only acquire the spin_lock of the
>> target cgroup itself; we do not attempt to **spin on any child cgroup's lock
>> while iterating through the descendants**.
> 
> Oh, I did not say anything about the current patch adding contention. I
> am suggesting we just keep using the global lock for the per-memcg
> cursors, if we keep them.
> 
> Right now, without this series, the global lock protects against
> concurrent changes to the global cursor from concurrent shrinkers. After
> the series, the only added contenders are userspace proactive writeback
> threads. Unless you have 10s or 100s of those, it should be fine to keep
> a single global lock, right?
> 

Ah yes, sorry about that, I misunderstood what you meant. Thanks a lot 
for the suggestion and for taking the time to explain it so patiently. 
I'll switch to using the global lock in v4 patch.


> Yes, userspace can affect writeback efficiency, but we can split the
> lock when it actually causes a problem.

Agreed.

> 
>>
>>
>>>>
>>>> So, should we keep the spin_lock or go with the cmpxchg() approach?
>>>> Yosry and Nhat, what are your thoughts on this?
>>>
>>> I think we should experiment with the global lock first. See if you
>>> observe any regressions with workloads that put a lot of pressure on the
>>> lock (a lot of threads in reclaim doing writeback + a few userspace
>>> threads doing proactive writeback). See if the userspace threads
>>> actually cause a meaningful regression.
>>
>> Sorry, it seems there are some implementation issues with the global lock
>> approach.
>>
>> In practice, our user-space agent mostly operates in the following two
>> scenarios:
>>   - Triggering proactive writeback on the same cgroup at different times
>> (sequentially).
>>   - Triggering proactive writeback on different cgroups at the same time
>> (concurrently).
>>
>> In both cases, there is no lock contention. So, the current lock works
>> perfectly fine for us.
> 
> Would using the existing global lock work for your use case? How many
> different cgroups can you end up reclaiming from concurrently?


It should work fine. We typically only have a dozen or so user-space 
agents triggering zswap writeback, and the critical section is very 
short anyway. I will implement this next.


Thanks,
Hao


^ permalink raw reply

* Re: [PATCH 1/1] mm/thp: clear deferred split shrinker bits when queues drain
From: Lance Yang @ 2026-06-03  2:00 UTC (permalink / raw)
  To: Andrew Morton
  Cc: david, ljs, shakeel.butt, mhocko, david, roman.gushchin,
	muchun.song, qi.zheng, yosry.ahmed, ziy, liam, usama.arif, kas,
	vbabka, ryncsn, zaslonko, gor, wangkefeng.wang, baolin.wang,
	baohua, dev.jain, npache, ryan.roberts, cgroups, linux-mm,
	linux-kernel, Johannes Weiner
In-Reply-To: <20260602133706.d737a82858d1cf89870521b1@linux-foundation.org>



On 2026/6/3 04:37, Andrew Morton wrote:
> On Tue,  2 Jun 2026 12:34:53 +0800 Lance Yang <lance.yang@linux.dev> wrote:
> 
>> From: Lance Yang <lance.yang@linux.dev>
>>
>> deferred_split_count() returns the raw list_lru count. When the per-memcg,
>> per-node list is empty, that count is 0.
>>
>> That skips scanning, but it does not tell memcg reclaim that the shrinker
>> is empty. shrink_slab_memcg() only clears the memcg shrinker bit when the
>> count callback reports SHRINK_EMPTY.
>>
>> Return SHRINK_EMPTY for an empty deferred split list, so the bit can be
>> cleared once the queue has drained.
>>
>> Signed-off-by: Lance Yang <lance.yang@linux.dev>
>> ---
>>   mm/huge_memory.c | 5 ++++-
>>   1 file changed, 4 insertions(+), 1 deletion(-)
>>
>> diff --git a/mm/huge_memory.c b/mm/huge_memory.c
>> index 72f6caf0fec6..62d598290c3b 100644
>> --- a/mm/huge_memory.c
>> +++ b/mm/huge_memory.c
>> @@ -4397,7 +4397,10 @@ void deferred_split_folio(struct folio *folio, bool partially_mapped)
>>   static unsigned long deferred_split_count(struct shrinker *shrink,
>>   		struct shrink_control *sc)
>>   {
>> -	return list_lru_shrink_count(&deferred_split_lru, sc);
>> +	unsigned long count;
>> +
>> +	count = list_lru_shrink_count(&deferred_split_lru, sc);
>> +	return count ?: SHRINK_EMPTY;
>>   }
>>   
>>   static bool thp_underused(struct folio *folio)
> 
> Should this be handled as a fix against hannes's "mm: switch deferred
> split shrinker to list_lru"?

Hmm ... I noticed this while looking at Johannes' work, but the
behavior is older than that ...

We also discussed the Fixes tag earlier[1] and decided to leave it
out. There is no missed reclaim, only some extra reclaim work :)

[1] 
https://lore.kernel.org/linux-mm/63797977-1c18-4885-8099-f5c21c80da39@linux.dev/

Cheers, Lance

^ permalink raw reply

* Re: [RFC PATCH 0/5] mm, swap: Virtual Swap Space (Swap Table Edition)
From: Yosry Ahmed @ 2026-06-03  1:29 UTC (permalink / raw)
  To: Nhat Pham
  Cc: kasong, Liam.Howlett, akpm, apopple, axelrasmussen, baohua,
	baolin.wang, bhe, byungchul, cgroups, chengming.zhou, chrisl,
	corbet, david, dev.jain, gourry, hannes, hughd, jannh,
	joshua.hahnjy, lance.yang, lenb, linux-doc, linux-kernel,
	linux-mm, linux-pm, lorenzo.stoakes, matthew.brost, mhocko,
	muchun.song, npache, pavel, peterx, peterz, pfalcato, rafael,
	rakie.kim, roman.gushchin, rppt, ryan.roberts, shakeel.butt,
	shikemeng, surenb, tglx, vbabka, weixugc, ying.huang, yosry.ahmed,
	yuanchu, zhengqi.arch, ziy, kernel-team, riel, haowenchao22
In-Reply-To: <20260528212955.1912856-1-nphamcs@gmail.com>

> II. Design
> 
> With vswap, pages are assigned virtual swap entries on a ghost device
> with no backing storage. These entries are backed by zswap, zero pages,
> or (lazily) physical swap slots. Physical backing is allocated only
> when needed — on zswap writeback or reclaim writeout, after the rmap
> step.
> 
> Compared to the standalone v6 implementation [1], which introduces a
> 24-byte per-entry swap descriptor and its own cluster allocator, this
> edition uses swap_table infrastructure, and share a lot of the allocator
> logic. Per-slot metadata is stored in a tag-encoded virtual_table
> (atomic_long_t, 8 bytes per slot), and physical clusters store
> Pointer-tagged rmap entries in the swap_table for reverse lookup back to
> the virtual cluster.
> 
> Here are some data layout diagrams:
> 
>   Case 1: vswap entry (virtualized)
> 
>   PTE                  swap_cluster_info_dynamic
>   vswap_entry          +-------------------------+
>   (swp_entry_t) ------>| swap_cluster_info (ci)  |
>                        | +--------------------+  |
>                        | | swap_table         |  |
>                        | |   PFN / Shadow     |  |
>                        | | memcg_table        |  |
>                        | | count,flags,order  |  |
>                        | | lock, list         |  |
>                        | +--------------------+  |
>                        |                         |
>                        | virtual_table           |
>                        | +--------------------+  |
>                        | | NONE               |  |
>                        | | PHYS               |  |
>                        | | ZERO               |  |
>                        | | ZSWAP(entry*)      |  |
>                        | | FOLIO(folio*)      |  |
>                        | +--------------------+  |
>                        +-------------------------+
>                               |
>                               | PHYS resolves to
>                               v
>                        PHYSICAL CLUSTER (swap_cluster_info)
>                        +--------------------------+
>                        | swap_table per-slot:     |
>                        |   NULL   - free          |
>                        |   PFN    - cached folio  |
>                        |   Shadow - swapped out   |
>                        |   Pointer- vswap rmap    |
>                        |   Bad    - unusable      |
>                        |                          |
>                        | Vswap-backing slot:      |
>                        |   Pointer(C|swp_entry_t) |
>                        |     rmap back to vswap   |
>                        +--------------------------+
> 
>   Case 2: direct-mapped physical entry (no vswap)
> 
>   PTE                  PHYSICAL CLUSTER (swap_cluster_info)
>   phys_entry           +--------------------------+
>   (swp_entry_t) ------>| swap_table per-slot:     |
>                        |   NULL   - free          |
>                        |   PFN    - cached folio  |
>                        |   Shadow - swapped out   |
>                        |   Bad    - unusable      |
>                        +--------------------------+
> 
> struct swap_cluster_info_dynamic {
>     struct swap_cluster_info ci;       /* swap_table, lock, etc. */
>     unsigned int index;                /* position in xarray */
>     struct rcu_head rcu;               /* kfree_rcu deferred free */
>     atomic_long_t *virtual_table;      /* backend info, 8 B/slot */
> };
> 
> Each vswap cluster (swap_cluster_info_dynamic) extends the classic
> swap_cluster_info struct with a virtual_table array that stores the
> backend information for each virtual swap entry in the cluster. Each
> entry is tag-encoded in the low 3 bits to indicate backend types:
> 
>   NONE:   |----- 0000 ------|000|  free / unbacked
>   PHYS:   |-- (type:5,off:N)|001|  on a physical swapfile (shifted)
>   ZERO:   |----- 0000 ------|010|  zero-filled page
>   ZSWAP:  |--- zswap_entry* |011|  compressed in zswap
>   FOLIO:  |--- folio* ------|100|  in-memory folio
> 
> We still have room for 3 more future backend types, for e.g. CRAM, i.e
> compressed-CXL-as-swap, which is laid out in [10] and [11]. Worst
> case scenario, we can add more fields to this extended struct.
> 
> Other design points:
> - Both vswap entries (Case 1) and directly-mapped physical entries
>   (Case 2) coexist as first-class citizens. All the common swap
>   code paths — swapout, swapin, swap freeing, swapoff, zswap
>   writeback, THP swapin, etc. work for both. When CONFIG_VSWAP=n,
>   the vswap branches compile out and behavior should be identical to
>   today's swap-table P4 (at least that is my intention).
> - Pointer-tagged swap_table on physical clusters for rmap (physical
>   -> virtual) lookup.
> - Virtual swap slots not backed by physical swap are not charged to
>   memcg swap counters — only physical backing is charged (I made the
>   case for this in [7]).
> - Careful separation of vswap and physical swap allocation paths and
>   structures adds a lot of complexity, but is crucial to make sure
>   both paths are efficient and do not conflict with each other (for
>   correctness and performance). I do re-use a lot of the allocation
>   logic wherever possible though.

Thanks for working on this! I mostly looked at the high-level design and
the zswap parts, as the swap code has changed a lot since I was familiar
with it :)

It seems like the direction being taken here is that we have one
(massive) vswap swap device, and we keep normal physical swap devices
around as well.

A vswap entry can point at a physical swap entry, or zswap, or zeromap.
If a vswap entry points at a physical swap entry, then the physical swap
entry points back at the vswap entry (a reverse mapping).

I assume the main reason here is to avoid the extra overhead if
everything uses vswap, which would mainly be the reverse mapping
overhead? I guess there's also some simplicity that comes from reusing
the swap info infra as a whole, including the swap table.

I don't like that the code bifurcates for vswap vs. normal swap entries
though. Not sure if this is an issue that can be fixed with proper
abstractions to hide it, or if the design needs modifications. I was
honestly really hoping we don't end up with this. I was hoping that the
physical swap device no longer uses a full swap table and all, and
everything goes through vswap.

I hoping that if redirection isn't needed (e.g. zswap is disabled),
vswap can directly encode the physical swap slot so that the reverse
mapping isn't needed -- so we avoid the overhead without keeping the
physical swap device using a fully-fledged swap table.

All that being said, perhaps I am too out of touch with the code to
realize it's simply not possible.

Honestly, if the main reason we can't have a single swap table for vswap
is saving 8 bytes on the reverse mapping, it sounds like a weak-ish
argument, even if we can't optimize the reverse mapping away. But maybe
I am also out of touch with RAM prices :)

I at least hope that, the current design is not painting us into a
corner (e.g. through userspace interfaces), and we can still achieve a
vswap-for-all implementation in the future (maybe that's what you have
in mind already?).

Aside from the swap code, the only sticking point for me is the logic
bifurcation in zswap. Why does zswap need to handle vswap vs. not vswap?
I thought the point of the design is to use vswap when zswap is used,
and otherwise use a normal swap table. In a way, one of the goals is to
make zswap a first class swap citizen, but it doesn't seem like we are
achieving that?

^ permalink raw reply

* Re: [PATCH v2] cgroup/cpuset: Change email address of Chen Ridong
From: Yosry Ahmed @ 2026-06-03  1:08 UTC (permalink / raw)
  To: Waiman Long
  Cc: Tejun Heo, Johannes Weiner, Michal Koutný, Ridong Chen,
	cgroups, linux-kernel
In-Reply-To: <20260602140819.265274-1-longman@redhat.com>

On Tue, Jun 02, 2026 at 10:08:19AM -0400, Waiman Long wrote:
> Chen Ridong has contributed quite a lot of fixes and cleanups to
> the cpuset code. Recently, his email address has been changed to
> ridong.chen@linux.dev. Update that in the MAINTAINERS file.

You probably want to update .mailmap too.

> 
> Signed-off-by: Waiman Long <longman@redhat.com>
> ---
>  MAINTAINERS | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 74c86cf9bc65..634eb67acd06 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -6526,7 +6526,7 @@ F:	include/linux/blk-cgroup.h
>  
>  CONTROL GROUP - CPUSET
>  M:	Waiman Long <longman@redhat.com>
> -R:	Chen Ridong <chenridong@huaweicloud.com>
> +R:	Ridong Chen <ridong.chen@linux.dev>
>  L:	cgroups@vger.kernel.org
>  S:	Maintained
>  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git
> -- 
> 2.54.0
> 
> 

^ permalink raw reply

* Re: [PATCH v3 1/4] mm/zswap: Make shrink_worker writeback cursor per-memcg
From: Yosry Ahmed @ 2026-06-02 23:19 UTC (permalink / raw)
  To: Hao Jia
  Cc: akpm, tj, hannes, shakeel.butt, mhocko, mkoutny, nphamcs,
	chengming.zhou, muchun.song, roman.gushchin, cgroups, linux-mm,
	linux-kernel, linux-doc, Hao Jia
In-Reply-To: <ff344c9f-51da-8b3a-e7a9-c4a7f4702ef8@gmail.com>

> > > > > Proactive writeback also wants a similar per-memcg cursor that is
> > > > > scoped to the specified memcg, so that repeated invocations against
> > > > > the same memcg make forward progress across its descendant memcgs
> > > > > instead of restarting from the first child memcg each time.
> > > > 
> > > > Is this a problem in practice?
> > > > 
> > > > Is the concern the overhead of scanning memcgs repeatedly, or lack of
> > > > fairness? I wonder if we should just do writeback in batches from all
> > > > memcgs, similar to how reclaim does it, then evaluate at the end if we
> > > > need to start over?
> > > > 
> > > 
> > > Not using a per-cgroup cursor will cause issues for "repeated small-budget
> > > calls" cases. For example, repeatedly triggering a 2MB writeback might
> > > result in only writing back pages from the first few child memcgs every
> > > time. In the worst-case scenario (where the writeback amount is less than
> > > WB_BATCH), it might only ever write back from the first child memcg.
> > 
> > Right, so a fairness concern?
> > 
> > I wonder if we should just reclaim a batch from each memcg, then check
> > if we reached the goal, otherwise start over. If the batch size is small
> > enough that should work?
> 
> Even with a small batch size, for small writeback requests triggered by
> user-space (e.g., 2MB, which is batch size * N), it might still repeatedly
> write back from only the first N child memcgs.

Yes, I understand, I am asking if this is a problem in practice. For
this to be a problem we'd need to trigger small writeback requests and
have many memcgs. 

> This could cause the user-space agent to prematurely give up on zswap
> writeback.

Why? The kernel should not return before trying to writeback from all
memcgs. If we scan the first N child memcgs and did not writeback
enough, we should keep going, right?

> > What if we do something like this (for the global cursor):
> > 
> > 	do {
> > 		memcg = xchg(zswap_next_shrink, NULL);
> > 		memcg = mem_cgroup_iter(NULL, memcg, NULL);
> > 		/* If the cursor was advanced from under us, try again */
> > 		if (!try_cmpxchg(zswap_next_shrink, NULL, memcg))
> > 			continue;
> > 	} while (..);
> > 			
> > 
> 
> Regarding the code above, IIRC, both the global and per-cgroup cursors
> suffer from race conditions. This race can cause mem_cgroup_iter(NULL, NULL,
> NULL) to return the root memcg or its descendants, leading zswap to write
> back pages from the wrong memcg.

Not the wrong memcg, it will just go back to the first memcg again,
which should be fine as I mentioned below.

> 
> Additionally, since mem_cgroup_iter() puts the prev memcg ref and gets the
> next memcg ref, a try_cmpxchg() failure on CPU1 might also lead to a ref
> leak for memcg1.
> 
> 
> 	CPU1                                       CPU2
> memcg1 = xchg(pos, NULL)
>                                memcg2 = xchg(pos, NULL) memcg2 = NULL;
> 
> memcg1 = mem_cgroup_iter()
>                        mem_cgroup_iter(NULL, **NULL**, NULL) error memcg
>                                 try_cmpxchg(pos,NULL,memcg2) succeed
> try_cmpxchg(pos,NULL,memcg1) **fail**

Yes, we can probably just take a ref on the memcg before calling
mem_cgroup_iter(). That being said, I think we can just keep the lock,
see below.

> 
> I took a stab at implementing a cmpxchg()-based zswap_mem_cgroup_iter()
> modeled after mem_cgroup_iter(), and it actually doesn't look that complex
> after all :)

I don't think we should re-implement mem_cgroup_iter() here.

[..]
> > There is a window where a racing shrinker will see the cursor as NULL
> > and start over, but that should be fine. We can generalize this for the
> > per-memcg cursor.
> > 
> > That being said..
> > 
> > > 
> > > Currently, this lock is only used in shrink_memcg(), proactive writeback,
> > > and mem_cgroup_css_offline(). Note that shrink_memcg() only acquires the
> > > lock of the root cgroup, and mem_cgroup_css_offline() is unlikely to be a
> > > hot path.
> > 
> > ..this made me realize it's probably fine to just use a global lock for
> > now?
> > 
> > IIUC the only additional contention to the existing lock will be from
> > userspace proactive writeback, and that shouldn't be a big deal
> > especially with the critical section being short?
> > 
> 
> In the current patch implementation, this lock protects the cgroup's own
> cursor variable. During each writeback, we only acquire the spin_lock of the
> target cgroup itself; we do not attempt to **spin on any child cgroup's lock
> while iterating through the descendants**.

Oh, I did not say anything about the current patch adding contention. I
am suggesting we just keep using the global lock for the per-memcg
cursors, if we keep them.

Right now, without this series, the global lock protects against
concurrent changes to the global cursor from concurrent shrinkers. After
the series, the only added contenders are userspace proactive writeback
threads. Unless you have 10s or 100s of those, it should be fine to keep
a single global lock, right?

Yes, userspace can affect writeback efficiency, but we can split the
lock when it actually causes a problem.

> 
> 
> > > 
> > > So, should we keep the spin_lock or go with the cmpxchg() approach?
> > > Yosry and Nhat, what are your thoughts on this?
> > 
> > I think we should experiment with the global lock first. See if you
> > observe any regressions with workloads that put a lot of pressure on the
> > lock (a lot of threads in reclaim doing writeback + a few userspace
> > threads doing proactive writeback). See if the userspace threads
> > actually cause a meaningful regression.
> 
> Sorry, it seems there are some implementation issues with the global lock
> approach.
> 
> In practice, our user-space agent mostly operates in the following two
> scenarios:
>  - Triggering proactive writeback on the same cgroup at different times
> (sequentially).
>  - Triggering proactive writeback on different cgroups at the same time
> (concurrently).
> 
> In both cases, there is no lock contention. So, the current lock works
> perfectly fine for us.

Would using the existing global lock work for your use case? How many
different cgroups can you end up reclaiming from concurrently?

> 
> However, if we really hate zswap_wb_iter.lock, I can try replacing it with
> the cmpxchg() approach.
> 
> Thanks,
> Hao

^ permalink raw reply

* [GIT PULL] cgroup: Fixes for v7.1-rc6
From: Tejun Heo @ 2026-06-02 22:47 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Johannes Weiner, Michal Koutny, Waiman Long, cgroups,
	linux-kernel

Hello,

A low-risk cpuset fix plus a MAINTAINERS email update.

The following changes since commit 22572dbcd3486e6c4dced877125bbf50e4e24edf:

  cgroup: rstat: relax NMI guard after switch to try_cmpxchg (2026-05-20 09:44:35 -1000)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git tags/cgroup-for-7.1-rc6-fixes

for you to fetch changes up to 57aff991119693e09b414aff3267c0eae5e81da0:

  cgroup/cpuset: Change Ridong's email (2026-06-02 11:28:54 -1000)

----------------------------------------------------------------
cgroup: Fixes for v7.1-rc6

One cpuset fix and a maintenance update, both low-risk:

- Fix cpuset partition CPU accounting under sibling CPU exclusion that could
  produce wrong CPU assignments and trigger scheduling-domain warnings.
  Includes selftests.

- Update an email address in MAINTAINERS.

----------------------------------------------------------------
Ridong Chen (1):
      cgroup/cpuset: Change Ridong's email

Sun Shaojie (2):
      cgroup/cpuset: Use effective_xcpus in partcmd_update add/del mask calculation
      cgroup/cpuset: Add test cases for sibling CPU exclusion on partition update

 MAINTAINERS                                       |  2 +-
 kernel/cgroup/cpuset.c                            | 13 +++++++------
 tools/testing/selftests/cgroup/test_cpuset_prs.sh | 10 ++++++++++
 3 files changed, 18 insertions(+), 7 deletions(-)

--
tejun

^ permalink raw reply

* Re: [PATCH v5 0/9] mm: switch THP shrinker to list_lru
From: Johannes Weiner @ 2026-06-02 21:46 UTC (permalink / raw)
  To: Lance Yang
  Cc: akpm, david, ljs, shakeel.butt, mhocko, david, roman.gushchin,
	muchun.song, qi.zheng, yosry.ahmed, ziy, liam, usama.arif, kas,
	vbabka, ryncsn, zaslonko, gor, baolin.wang, baohua, dev.jain,
	npache, ryan.roberts, cgroups, linux-mm, linux-kernel
In-Reply-To: <20260601083652.59539-1-lance.yang@linux.dev>

On Mon, Jun 01, 2026 at 04:36:52PM +0800, Lance Yang wrote:
> As the changelog above says, the old queue is per-memcg only, rather
> than per-memcg-per-node. So reclaim on one node can still walk the whole
> memcg queue and split underused THPs from other nodes in the same memcg.
> 
> But I think the new one can lose reclaim in the cgroup.memory=nokmem
> case ...
> 
> With nokmem, the deferred shrinker can still run from memcg reclaim,
> because it is SHRINKER_NONSLAB. But the list_lru is no longer per-memcg:
> 
> __list_lru_init() clears memcg_aware,
> 
> 	if (mem_cgroup_kmem_disabled())
> 		memcg_aware = false;
> 
> so list_lru_from_memcg_idx() falls back to the shared node list:
> 
> static inline struct list_lru_one *
> list_lru_from_memcg_idx(struct list_lru *lru, int nid, int idx)
> {
> 	if (list_lru_memcg_aware(lru) && idx >= 0) {
> [...]
> 	}
> 	return &lru->node[nid].lru;
> }
> 
> That makes the shrinker bit unreliable. __list_lru_add() still sets the
> bit on the memcg passed in, but only when the list goes from empty to
> non-empty:
> 
> bool __list_lru_add(struct list_lru *lru, struct list_lru_one *l,
> 		    struct list_head *item, int nid,
> 		    struct mem_cgroup *memcg)
> {
> 	if (list_empty(item)) {
> [...]
> 		if (!l->nr_items++)
> 			set_shrinker_bit(memcg, nid, lru_shrinker_id(lru));
> [...]
> 		return true;
> 	}
> 	return false;
> }
> 
> If memcg A adds the first folio, A gets the bit. If memcg B later adds a
> folio to the same shared list, B does not get a bit, because the list
> was already non-empty.
> 
> So in the A-first/B-later case, reclaim from B may not call the deferred
> shrinker at all. The shared list is scanned from memcg reclaim only if
> reclaim runs from the memcg that has the bit, such as A here, or from
> global reclaim :)
> 
> Anyway, only after the shared list is emptied does the next memcg to add
> a folio get to be the one with the bit, IIUC :)

Sorry for the delay, this took me a bit to think about. The shrinker
code is a mess.

I read it the same way you do. And this is true for all list_lru users
when nokmem is set: we just set random nonsense shrinker bits.

HOWEVER, the generic shrinker code fixes that up by IGNORING random
shrinker bits like this when !memcg_kmem_online(). And shrinking
correctly happens only against the shared root queue when the reclaim
iterator walks root_mem_cgroup.

HOWEVER, the THP shrinker explicitly sets SHRINKER_NONSLAB, which in
turn overrides the previous override. So yes there is a weirdness: we
get the root cgroup invocation against the shared queue, and then one
more time triggered by that random memcg bit.

The most direct fix is to just drop SHRINKER_NONSLAB. It declares
independence from kmem, which is no longer true.

Cleaning up the shrinker code is left for another day.

Andrew, if there are no objections, can you please fold this?

---

From 6787efabb9584824c196bf01c517d93aae3764c3 Mon Sep 17 00:00:00 2001
From: Johannes Weiner <hannes@cmpxchg.org>
Date: Tue, 2 Jun 2026 17:11:46 -0400
Subject: [PATCH] mm: switch deferred split shrinker to list_lru fix

Lance Yang points out a weirdness in the list_lru code with
cgroup.memory=nokmem: in this mode, list_lru collapses to a shared
per-node list that holds the folios, but __list_lru_add() still sets
the shrinker bit on the owning memcg.

Usually this is fine, because the generic shrinker code ignores these
random bits when !memcg_kmem_online(). But the THP shrinker still has
the SHRINKER_NONSLAB flag set, which specifically declares an
independence from kmem. As a result, the shrinker fires twice per
reclaim cycle: one during the regular root cgroup scan, and then one
more time triggered from whichever memcg got the shrinker bit.

Drop the flag, since it's no longer true. The deferred_split shrinker
then behaves like every other list_lru-backed shrinker under nokmem,
including the non-kmem ones (zswap, workingset shadow_nodes): skipped
from memcg-internal reclaim, driven by global reclaim only.

This needs proper cleaning up on the shrinker and list_lru side, but
that's scope for a follow-up series. Just make it consistent now.

Reported-by: Lance Yang <lance.yang@linux.dev>
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
 mm/huge_memory.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 72f6caf0fec6..aef495891f8c 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -956,8 +956,7 @@ int folio_memcg_alloc_deferred(struct folio *folio)
 static int __init thp_shrinker_init(void)
 {
 	deferred_split_shrinker = shrinker_alloc(SHRINKER_NUMA_AWARE |
-						 SHRINKER_MEMCG_AWARE |
-						 SHRINKER_NONSLAB,
+						 SHRINKER_MEMCG_AWARE,
 						 "thp-deferred_split");
 	if (!deferred_split_shrinker)
 		return -ENOMEM;
-- 
2.54.0


^ permalink raw reply related

* Re: [PATCH] cgroup/cpuset: change ridong's email
From: Tejun Heo @ 2026-06-02 21:31 UTC (permalink / raw)
  To: Ridong Chen
  Cc: Waiman Long, Johannes Weiner, Michal Koutný, cgroups,
	linux-kernel
In-Reply-To: <20260602091038.26901-1-ridong.chen@linux.dev>

Applied to cgroup/for-7.1-fixes with Waiman's ack.

Thanks.
--
tejun

^ permalink raw reply

* Re: [PATCH 1/1] mm/thp: clear deferred split shrinker bits when queues drain
From: Andrew Morton @ 2026-06-02 20:37 UTC (permalink / raw)
  To: Lance Yang
  Cc: david, ljs, shakeel.butt, mhocko, david, roman.gushchin,
	muchun.song, qi.zheng, yosry.ahmed, ziy, liam, usama.arif, kas,
	vbabka, ryncsn, zaslonko, gor, wangkefeng.wang, baolin.wang,
	baohua, dev.jain, npache, ryan.roberts, cgroups, linux-mm,
	linux-kernel, Johannes Weiner
In-Reply-To: <20260602043453.67597-1-lance.yang@linux.dev>

On Tue,  2 Jun 2026 12:34:53 +0800 Lance Yang <lance.yang@linux.dev> wrote:

> From: Lance Yang <lance.yang@linux.dev>
> 
> deferred_split_count() returns the raw list_lru count. When the per-memcg,
> per-node list is empty, that count is 0.
> 
> That skips scanning, but it does not tell memcg reclaim that the shrinker
> is empty. shrink_slab_memcg() only clears the memcg shrinker bit when the
> count callback reports SHRINK_EMPTY.
> 
> Return SHRINK_EMPTY for an empty deferred split list, so the bit can be
> cleared once the queue has drained.
> 
> Signed-off-by: Lance Yang <lance.yang@linux.dev>
> ---
>  mm/huge_memory.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/mm/huge_memory.c b/mm/huge_memory.c
> index 72f6caf0fec6..62d598290c3b 100644
> --- a/mm/huge_memory.c
> +++ b/mm/huge_memory.c
> @@ -4397,7 +4397,10 @@ void deferred_split_folio(struct folio *folio, bool partially_mapped)
>  static unsigned long deferred_split_count(struct shrinker *shrink,
>  		struct shrink_control *sc)
>  {
> -	return list_lru_shrink_count(&deferred_split_lru, sc);
> +	unsigned long count;
> +
> +	count = list_lru_shrink_count(&deferred_split_lru, sc);
> +	return count ?: SHRINK_EMPTY;
>  }
>  
>  static bool thp_underused(struct folio *folio)

Should this be handled as a fix against hannes's "mm: switch deferred
split shrinker to list_lru"?

^ permalink raw reply

* Re: [PATCH-next v5 1/6] cgroup/cpuset: Fix node inconsistencies between cpuset_update_tasks_nodemask() and cpuset_attach()
From: Waiman Long @ 2026-06-02 18:43 UTC (permalink / raw)
  To: Ridong Chen, Tejun Heo, Johannes Weiner, Michal Koutný,
	Peter Zijlstra
  Cc: cgroups, linux-kernel, Aaron Tomlin, Guopeng Zhang
In-Reply-To: <a69816f1-6cce-4123-92ec-1ade963061f9@linux.dev>

On 6/2/26 9:37 AM, Ridong Chen wrote:
>
> On 2026/6/2 10:31, Waiman Long wrote:
>> Whenever memory node mask is changed, there are 4 places where the node
>> mask has to be updated or used.
>>   1) task's node mask via cpuset_change_task_nodemask()
>>   2) memory policy binding via mpol_rebind_mm()
>>   3) if memory migration is enabled, migrate from old_mems_allowed to
>>      the new node mask via cpuset_migrate_mm().
>>   4) setting old_mems_allowed
>>
>> These memory actions are done in cpuset_update_tasks_nodemask() and
>> cpuset_attach(). However there are inconsistencies in what node masks
>> are being used in these 2 functions.
>>
>> In cpuset_update_tasks_nodemask(),
>>   - cpuset_change_task_nodemask(): guarantee_online_mems()
>>   - mpol_rebind_mm(): mems_allowed
>>   - cpuset_migrate_mm(): guarantee_online_mems()
>>   - old_mems_allowed: guarantee_online_mems()
>>
>> In cpuset_attach(),
>>   - cpuset_change_task_nodemask(): guarantee_online_mems()
>>   - mpol_rebind_mm(): effective_mems
>>   - cpuset_migrate_mm(): effective_mems
>>   - old_mems_allowed: effective_mems
>>
>> These inconsistencies dates back to quite a long time ago and it is
>> hard to say what should be the correct values.
>>
>> The guarantee_online_mems() function returns a node mask from current or
>> an ancestor cpuset that is a subset of node_states[N_MEMORY]. Nodes in
>> node_states[N_MEMORY] are all online, i.e. in node_states[N_ONLINE].
>> However, node in node_states[N_ONLINE] may not have memory. So
>> node_states[N_MEMORY] should be a subset of node_states[N_ONLINE].
>>
>> The guarantee_online_mems() function should only be useful for v1 where
>> mems_allowed is the same as effective_mems. With v2, the memory nodes
>> in effective_mems should always be a subset of node_states[N_MEMORY].
>> The only time that may not be true is when a memory hot-unplug operation
>> is in progress and a memory node is removed from node_states[N_MEMORY]
>> but not yet reflected in effective_mems as cpuset_handle_hotplug()
>> has not yet been called from cpuset_track_online_nodes(). When
>> cpuset_handle_hotplug() is called later, the memory node setting
>> of the relevant cpusets and tasks will be updated. So replacing the
>> guarantee_online_mems() call by just using cs->effective_mems should
>> be fine.
>>
> I noticed this pattern in several places:
>
> ```
> if (cpuset_v2())
> 	newmems = cs->effective_mems;
> else
> 	guarantee_online_mems(cs, &newmems);
> ```
>
> Would it be simpler to move the v2 logic into guarantee_online_mems?
>
> ```
> static void guarantee_online_mems(struct cpuset *cs, nodemask_t *pmask)
> {
> 	if (cpuset_v2()) {
> 		*pmask = cs->effective_mems;
> 		return;
> 	}
> 	while (!nodes_and(*pmask, cs->effective_mems, node_states[N_MEMORY]))
> 		cs = parent_cs(cs);
> }
> ```
Yes, it makes sense to put it directly into guarantee_online_mems().
>> Let use the following setup for both of them and make them consistent.
>>   - cpuset_change_task_nodemask(): guarantee_online_mems()
>>   - mpol_rebind_mm(): effective_mems
>>   - cpuset_migrate_mm(): guarantee_online_mems()
>>   - old_mems_allowed: guarantee_online_mems()
>>
>> So for v2, it is effectively all effective_mems. For v1, mpol_rebind_mm()
>> uses cpus_allowed which may differ from what guarantee_online_mems()
> 	^
> mems_allowed?

Thanks for catching it. Will fix that and update your email address in 
the next version.

Cheers,
Longman

>> returns.
>>
>> Signed-off-by: Waiman Long <longman@redhat.com>
>> ---
>>   kernel/cgroup/cpuset.c | 32 +++++++++++++++++++++-----------
>>   1 file changed, 21 insertions(+), 11 deletions(-)
>>
>> diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
>> index 6bdb68689c24..987456b6d879 100644
>> --- a/kernel/cgroup/cpuset.c
>> +++ b/kernel/cgroup/cpuset.c
>> @@ -2616,6 +2616,13 @@ static void *cpuset_being_rebound;
>>    * Iterate through each task of @cs updating its mems_allowed to the
>>    * effective cpuset's.  As this function is called with cpuset_mutex held,
>>    * cpuset membership stays stable.
>> + *
>> + * - cpuset_change_task_nodemask(): guarantee_online_mems()
>> + * - mpol_rebind_mm(): effective_mems
>> + * - cpuset_migrate_mm(): guarantee_online_mems()
>> + * - old_mems_allowed: guarantee_online_mems()
>> + *
>> + * For v2, guarantee_online_mems() should just return effective_mems.
> I agree, but the implementation is not as simple as what I mentioned above.
>
>>    */
>>   void cpuset_update_tasks_nodemask(struct cpuset *cs)
>>   {
>> @@ -2625,7 +2632,10 @@ void cpuset_update_tasks_nodemask(struct cpuset *cs)
>>   
>>   	cpuset_being_rebound = cs;		/* causes mpol_dup() rebind */
>>   
>> -	guarantee_online_mems(cs, &newmems);
>> +	if (cpuset_v2())
>> +		newmems = cs->effective_mems;
>> +	else
>> +		guarantee_online_mems(cs, &newmems);
>>   
>>   	/*
>>   	 * The mpol_rebind_mm() call takes mmap_lock, which we couldn't
>> @@ -2650,7 +2660,7 @@ void cpuset_update_tasks_nodemask(struct cpuset *cs)
>>   
>>   		migrate = is_memory_migrate(cs);
>>   
>> -		mpol_rebind_mm(mm, &cs->mems_allowed);
>> +		mpol_rebind_mm(mm, &cs->effective_mems);
>>   		if (migrate)
>>   			cpuset_migrate_mm(mm, &cs->old_mems_allowed, &newmems);
>>   		else
>> @@ -3148,17 +3158,18 @@ static void cpuset_attach(struct cgroup_taskset *tset)
>>   
>>   	/*
>>   	 * In the default hierarchy, enabling cpuset in the child cgroups
>> -	 * will trigger a number of cpuset_attach() calls with no change
>> -	 * in effective cpus and mems. In that case, we can optimize out
>> -	 * by skipping the task iteration and update.
>> +	 * will trigger a cpuset_attach() call with no change in effective cpus
>> +	 * and mems. In that case, we can optimize out by skipping the task
>> +	 * iteration and update.
>>   	 */
>> -	if (cpuset_v2() && !cpus_updated && !mems_updated) {
>> +	if (cpuset_v2()) {
>>   		cpuset_attach_nodemask_to = cs->effective_mems;
>> -		goto out;
>> +		if (!cpus_updated && !mems_updated)
>> +			goto out;
>> +	} else {
>> +		guarantee_online_mems(cs, &cpuset_attach_nodemask_to);
>>   	}
>>   
>> -	guarantee_online_mems(cs, &cpuset_attach_nodemask_to);
>> -
>>   	cgroup_taskset_for_each(task, css, tset)
>>   		cpuset_attach_task(cs, task);
>>   
>> @@ -3168,7 +3179,6 @@ static void cpuset_attach(struct cgroup_taskset *tset)
>>   	 * if there is no change in effective_mems and CS_MEMORY_MIGRATE is
>>   	 * not set.
>>   	 */
>> -	cpuset_attach_nodemask_to = cs->effective_mems;
>>   	if (!is_memory_migrate(cs) && !mems_updated)
>>   		goto out;
>>   
>> @@ -3176,7 +3186,7 @@ static void cpuset_attach(struct cgroup_taskset *tset)
>>   		struct mm_struct *mm = get_task_mm(leader);
>>   
>>   		if (mm) {
>> -			mpol_rebind_mm(mm, &cpuset_attach_nodemask_to);
>> +			mpol_rebind_mm(mm, &cs->effective_mems);
>>   
>>   			/*
>>   			 * old_mems_allowed is the same with mems_allowed


^ permalink raw reply

* Re: [PATCH v2] cgroup/cpuset: Fix update_prstate() always returning 0 on partition errors
From: Waiman Long @ 2026-06-02 18:41 UTC (permalink / raw)
  To: Michal Koutný, Tao Cui
  Cc: chenridong, tj, hannes, cgroups, linux-kernel, Tao Cui
In-Reply-To: <ah6JpNvdO7vaBmjS@localhost.localdomain>


On 6/2/26 3:46 AM, Michal Koutný wrote:
> Hi.
>
> On Tue, Jun 02, 2026 at 12:55:21PM +0800, Tao Cui <cui.tao@linux.dev> wrote:
>> update_prstate() stores the error code in cs->prs_err and transitions
>> the partition to an invalid state, but always returns 0. The caller
>> cpuset_partition_write() uses "return retval ?: nbytes", so the write
>> syscall always appears to succeed from userspace even when the partition
>> became invalid.
>> Return -EINVAL when err is set so userspace can detect
>> the failure immediately.
> This is quite a visible UAPI change (a write can succeed to invalidate a
> partition) and users are meant to watch for cpuset.cpus.partition state
> anyway for asynchronous changes.

Right, it is purposely done to not return a write error when writing any 
cpuset control files. The only exception is cpuset.cpus.exclusive which 
can return failure when  an exclusive CPU has been taken. It is 
documented in cgroup-v2.rst.

Cheers,
Longman


^ permalink raw reply

* Re: [PATCH] cgroup/cpuset: Remove Chen Ridong as a cpust reviewer for now
From: Waiman Long @ 2026-06-02 18:35 UTC (permalink / raw)
  To: Ridong Chen, Michal Koutný
  Cc: Tejun Heo, Johannes Weiner, cgroups, linux-kernel
In-Reply-To: <69b82f73-e89a-4271-a494-3c4d5684b7ac@linux.dev>


On 6/2/26 4:13 AM, Ridong Chen wrote:
>
> On 2026/6/2 15:51, Michal Koutný wrote:
>> +Cc: ridong.chen@linux.dev
>>
>> (This looks like their new address.)
>>
> Hi all,
>
> Thank you, Michal.
>
> Apologies for the email issue. I'm currently changing my company, The
> ridong.chen@linux.dev email is valid.

I am glad that you are showing up again. I was wondering where you had been.

Cheers,
Longman

>
>
>> On Mon, Jun 01, 2026 at 10:44:22PM -0400, Waiman Long <longman@redhat.com> wrote:
>>> Chen Ridong has contributed quite a lot of fixes and cleanups to the
>>> cpuset code. Unfortunately, his email address is now no longer valid. So
>>> remove him as a cpuset reviewer until he shows up again or someone else
>>> volunteers to take his place.
>>>
>>> Signed-off-by: Waiman Long <longman@redhat.com>
>>> ---
>>>   MAINTAINERS | 1 -
>>>   1 file changed, 1 deletion(-)
>>>
>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>> index 74c86cf9bc65..c7a7126ea406 100644
>>> --- a/MAINTAINERS
>>> +++ b/MAINTAINERS
>>> @@ -6526,7 +6526,6 @@ F:	include/linux/blk-cgroup.h
>>>   
>>>   CONTROL GROUP - CPUSET
>>>   M:	Waiman Long <longman@redhat.com>
>>> -R:	Chen Ridong <chenridong@huaweicloud.com>
>>>   L:	cgroups@vger.kernel.org
>>>   S:	Maintained
>>>   T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git
>>> -- 
>>> 2.54.0
>>>


^ permalink raw reply

* Re: [PATCH] cgroup: Migrate tasks to the root css when a controller is rebound
From: Tejun Heo @ 2026-06-02 18:34 UTC (permalink / raw)
  To: cgroups, linux-kernel
  Cc: Mark Brown, Bert Karwatzki, Johannes Weiner, Michal Koutný,
	Sebastian Andrzej Siewior, Petr Malat, kernel test robot,
	Martin Pitt, Aishwarya.TCV
In-Reply-To: <20260601190256.1815778-1-tj@kernel.org>

Applied to cgroup/for-7.2.

Thanks Mark and Bert for the reports and the testing.

--
tejun

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox