mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCHv6 0/2] sched/deadline: Walk up cpuset hierarchy to decide root domain when hot-unplug
@ 2025-11-17  9:27 Pingfan Liu
  2025-11-17  9:27 ` [PATCHv6 1/2] cgroup/cpuset: Introduce cpuset_cpus_allowed_locked() Pingfan Liu
  2025-11-17  9:27 ` [PATCHv6 2/2] sched/deadline: Walk up cpuset hierarchy to decide root domain when hot-unplug Pingfan Liu
  0 siblings, 2 replies; 8+ messages in thread
From: Pingfan Liu @ 2025-11-17  9:27 UTC (permalink / raw)
  Cc: Pingfan Liu, Waiman Long, Chen Ridong, Peter Zijlstra,
	Juri Lelli, Pierre Gondois, Ingo Molnar, Vincent Guittot,
	Dietmar Eggemann, Steven Rostedt, Ben Segall, Mel Gorman,
	Valentin Schneider, Tejun Heo, Johannes Weiner, mkoutny,
	linux-kernel

This series fixes a deadline bug triggered during CPU hot-removal, which
prevents the CPU from being removed. For details, please refer to the
commit log in [2/2].  In addition, [1/2] exposes the
cpuset_cpus_allowed_locked() interface for use by [2/2].

v5 -> v6:
  Introduce the cpuset_cpus_allowed_locked() variant (thanks to Waiman)
  Use local_cpu_mask_dl to avoid cpumask allocation on the stack (thanks to Juri and Waiman)

v4 -> v5:
  Move the housekeeping part into deadline.c (Thanks for Waiman's suggestion)
  Use cpuset_cpus_allowed() instead of introducing new cpuset function (Thanks for Ridong's suggestion)

Pingfan Liu (2):
  cgroup/cpuset: Introduce cpuset_cpus_allowed_locked()
  sched/deadline: Walk up cpuset hierarchy to decide root domain when
    hot-unplug

 include/linux/cpuset.h  |  1 +
 kernel/cgroup/cpuset.c  | 51 ++++++++++++++++++++++++++------------
 kernel/sched/deadline.c | 54 ++++++++++++++++++++++++++++++++++++-----
 3 files changed, 85 insertions(+), 21 deletions(-)

-- 
2.49.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCHv6 1/2] cgroup/cpuset: Introduce cpuset_cpus_allowed_locked()
  2025-11-17  9:27 [PATCHv6 0/2] sched/deadline: Walk up cpuset hierarchy to decide root domain when hot-unplug Pingfan Liu
@ 2025-11-17  9:27 ` Pingfan Liu
  2025-11-17 20:37   ` Waiman Long
  2025-11-17  9:27 ` [PATCHv6 2/2] sched/deadline: Walk up cpuset hierarchy to decide root domain when hot-unplug Pingfan Liu
  1 sibling, 1 reply; 8+ messages in thread
From: Pingfan Liu @ 2025-11-17  9:27 UTC (permalink / raw)
  To: cgroups
  Cc: Pingfan Liu, Waiman Long, Chen Ridong, Peter Zijlstra,
	Juri Lelli, Pierre Gondois, Ingo Molnar, Vincent Guittot,
	Dietmar Eggemann, Steven Rostedt, Ben Segall, Mel Gorman,
	Valentin Schneider, Tejun Heo, Johannes Weiner, mkoutny,
	linux-kernel

cpuset_cpus_allowed() uses a reader lock that is sleepable under RT,
which means it cannot be called inside raw_spin_lock_t context.

Introduce a new cpuset_cpus_allowed_locked() helper that performs the
same function as cpuset_cpus_allowed() except that the caller must have
acquired the cpuset_mutex so that no further locking will be needed.

Suggested-by: Waiman Long <longman@redhat.com>
Signed-off-by: Pingfan Liu <piliu@redhat.com>
Cc: Waiman Long <longman@redhat.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: "Michal Koutný" <mkoutny@suse.com>
Cc: linux-kernel@vger.kernel.org
To: cgroups@vger.kernel.org
---
 include/linux/cpuset.h |  1 +
 kernel/cgroup/cpuset.c | 51 +++++++++++++++++++++++++++++-------------
 2 files changed, 37 insertions(+), 15 deletions(-)

diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index 2ddb256187b51..e057a3123791e 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -75,6 +75,7 @@ extern void dec_dl_tasks_cs(struct task_struct *task);
 extern void cpuset_lock(void);
 extern void cpuset_unlock(void);
 extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask);
+extern void cpuset_cpus_allowed_locked(struct task_struct *p, struct cpumask *mask);
 extern bool cpuset_cpus_allowed_fallback(struct task_struct *p);
 extern bool cpuset_cpu_is_isolated(int cpu);
 extern nodemask_t cpuset_mems_allowed(struct task_struct *p);
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 52468d2c178a3..7a179a1a2e30a 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -4116,24 +4116,13 @@ void __init cpuset_init_smp(void)
 	BUG_ON(!cpuset_migrate_mm_wq);
 }
 
-/**
- * cpuset_cpus_allowed - return cpus_allowed mask from a tasks cpuset.
- * @tsk: pointer to task_struct from which to obtain cpuset->cpus_allowed.
- * @pmask: pointer to struct cpumask variable to receive cpus_allowed set.
- *
- * Description: Returns the cpumask_var_t cpus_allowed of the cpuset
- * attached to the specified @tsk.  Guaranteed to return some non-empty
- * subset of cpu_active_mask, even if this means going outside the
- * tasks cpuset, except when the task is in the top cpuset.
- **/
-
-void cpuset_cpus_allowed(struct task_struct *tsk, struct cpumask *pmask)
+/*
+ * Return cpus_allowed mask from a task's cpuset.
+ */
+static void __cpuset_cpus_allowed_locked(struct task_struct *tsk, struct cpumask *pmask)
 {
-	unsigned long flags;
 	struct cpuset *cs;
 
-	spin_lock_irqsave(&callback_lock, flags);
-
 	cs = task_cs(tsk);
 	if (cs != &top_cpuset)
 		guarantee_active_cpus(tsk, pmask);
@@ -4153,7 +4142,39 @@ void cpuset_cpus_allowed(struct task_struct *tsk, struct cpumask *pmask)
 		if (!cpumask_intersects(pmask, cpu_active_mask))
 			cpumask_copy(pmask, possible_mask);
 	}
+}
 
+/**
+ * cpuset_cpus_allowed_locked - return cpus_allowed mask from a task's cpuset.
+ * @tsk: pointer to task_struct from which to obtain cpuset->cpus_allowed.
+ * @pmask: pointer to struct cpumask variable to receive cpus_allowed set.
+ *
+ * Similir to cpuset_cpus_allowed() except that the caller must have acquired
+ * cpuset_mutex.
+ */
+void cpuset_cpus_allowed_locked(struct task_struct *tsk, struct cpumask *pmask)
+{
+	lockdep_assert_held(&cpuset_mutex);
+	__cpuset_cpus_allowed_locked(tsk, pmask);
+}
+
+/**
+ * cpuset_cpus_allowed - return cpus_allowed mask from a task's cpuset.
+ * @tsk: pointer to task_struct from which to obtain cpuset->cpus_allowed.
+ * @pmask: pointer to struct cpumask variable to receive cpus_allowed set.
+ *
+ * Description: Returns the cpumask_var_t cpus_allowed of the cpuset
+ * attached to the specified @tsk.  Guaranteed to return some non-empty
+ * subset of cpu_active_mask, even if this means going outside the
+ * tasks cpuset, except when the task is in the top cpuset.
+ **/
+
+void cpuset_cpus_allowed(struct task_struct *tsk, struct cpumask *pmask)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&callback_lock, flags);
+	__cpuset_cpus_allowed_locked(tsk, pmask);
 	spin_unlock_irqrestore(&callback_lock, flags);
 }
 
-- 
2.49.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCHv6 2/2] sched/deadline: Walk up cpuset hierarchy to decide root domain when hot-unplug
  2025-11-17  9:27 [PATCHv6 0/2] sched/deadline: Walk up cpuset hierarchy to decide root domain when hot-unplug Pingfan Liu
  2025-11-17  9:27 ` [PATCHv6 1/2] cgroup/cpuset: Introduce cpuset_cpus_allowed_locked() Pingfan Liu
@ 2025-11-17  9:27 ` Pingfan Liu
  2025-11-17 11:00   ` kernel test robot
  2025-11-17 11:00   ` kernel test robot
  1 sibling, 2 replies; 8+ messages in thread
From: Pingfan Liu @ 2025-11-17  9:27 UTC (permalink / raw)
  To: linux-kernel
  Cc: Pingfan Liu, Waiman Long, Chen Ridong, Peter Zijlstra,
	Juri Lelli, Pierre Gondois, Ingo Molnar, Vincent Guittot,
	Dietmar Eggemann, Steven Rostedt, Ben Segall, Mel Gorman,
	Valentin Schneider, Tejun Heo, Johannes Weiner, mkoutny

*** Bug description ***
When testing kexec-reboot on a 144 cpus machine with
isolcpus=managed_irq,domain,1-71,73-143 in kernel command line, I
encounter the following bug:

[   97.114759] psci: CPU142 killed (polled 0 ms)
[   97.333236] Failed to offline CPU143 - error=-16
[   97.333246] ------------[ cut here ]------------
[   97.342682] kernel BUG at kernel/cpu.c:1569!
[   97.347049] Internal error: Oops - BUG: 00000000f2000800 [#1] SMP
[...]

In essence, the issue originates from the CPU hot-removal process, not
limited to kexec. It can be reproduced by writing a SCHED_DEADLINE
program that waits indefinitely on a semaphore, spawning multiple
instances to ensure some run on CPU 72, and then offlining CPUs 1–143
one by one. When attempting this, CPU 143 failed to go offline.
  bash -c 'taskset -cp 0 $$ && for i in {1..143}; do echo 0 > /sys/devices/system/cpu/cpu$i/online 2>/dev/null; done'

Tracking down this issue, I found that dl_bw_deactivate() returned
-EBUSY, which caused sched_cpu_deactivate() to fail on the last CPU.
But that is not the fact, and contributed by the following factors:
When a CPU is inactive, cpu_rq()->rd is set to def_root_domain. For an
blocked-state deadline task (in this case, "cppc_fie"), it was not
migrated to CPU0, and its task_rq() information is stale. So its rq->rd
points to def_root_domain instead of the one shared with CPU0.  As a
result, its bandwidth is wrongly accounted into a wrong root domain
during domain rebuild.

*** Issue ***
The key point is that root_domain is only tracked through active rq->rd.
To avoid using a global data structure to track all root_domains in the
system, there should be a method to locate an active CPU within the
corresponding root_domain.

*** Solution ***
To locate the active cpu, the following rules for deadline
sub-system is useful
  -1.any cpu belongs to a unique root domain at a given time
  -2.DL bandwidth checker ensures that the root domain has active cpus.

Now, let's examine the blocked-state task P.
If P is attached to a cpuset that is a partition root, it is
straightforward to find an active CPU.
If P is attached to a cpuset that has changed from 'root' to 'member',
the active CPUs are grouped into the parent root domain. Naturally, the
CPUs' capacity and reserved DL bandwidth are taken into account in the
ancestor root domain. (In practice, it may be unsafe to attach P to an
arbitrary root domain, since that domain may lack sufficient DL
bandwidth for P.) Again, it is straightforward to find an active CPU in
the ancestor root domain.

This patch groups CPUs into isolated and housekeeping sets. For the
housekeeping group, it walks up the cpuset hierarchy to find active CPUs
in P's root domain and retrieves the valid rd from cpu_rq(cpu)->rd.

Signed-off-by: Pingfan Liu <piliu@redhat.com>
Cc: Waiman Long <longman@redhat.com>
Cc: Chen Ridong <chenridong@huaweicloud.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Juri Lelli <juri.lelli@redhat.com>
Cc: Pierre Gondois <pierre.gondois@arm.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Vincent Guittot <vincent.guittot@linaro.org>
Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Ben Segall <bsegall@google.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Valentin Schneider <vschneid@redhat.com>
To: linux-kernel@vger.kernel.org
---
 kernel/sched/deadline.c | 54 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 48 insertions(+), 6 deletions(-)

diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index 7b7671060bf9e..194a341e85864 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -2465,6 +2465,7 @@ static struct task_struct *pick_earliest_pushable_dl_task(struct rq *rq, int cpu
 	return NULL;
 }
 
+/* Access rule: must be called on local CPU with preemption disabled */
 static DEFINE_PER_CPU(cpumask_var_t, local_cpu_mask_dl);
 
 static int find_later_rq(struct task_struct *task)
@@ -2907,11 +2908,43 @@ void __init init_sched_dl_class(void)
 					GFP_KERNEL, cpu_to_node(i));
 }
 
+/*
+ * This function always returns a non-empty bitmap in @cpus. This is because
+ * if a root domain has reserved bandwidth for DL tasks, the DL bandwidth
+ * check will prevent CPU hotplug from deactivating all CPUs in that domain.
+ */
+static void dl_get_task_effective_cpus(struct task_struct *p, struct cpumask *cpus)
+{
+	const struct cpumask *hk_msk;
+
+	hk_msk = housekeeping_cpumask(HK_TYPE_DOMAIN);
+	if (housekeeping_enabled(HK_TYPE_DOMAIN)) {
+		if (!cpumask_intersects(p->cpus_ptr, hk_msk)) {
+			/*
+			 * CPUs isolated by isolcpu="domain" always belong to
+			 * def_root_domain.
+			 */
+			cpumask_andnot(cpus, cpu_active_mask, hk_msk);
+			return;
+		}
+	}
+
+	/*
+	 * If a root domain holds a DL task, it must have active CPUs. So
+	 * active CPUs can always be found by walking up the task's cpuset
+	 * hierarchy up to the partition root.
+	 */
+	cpuset_cpus_allowed_locked(p, cpus);
+}
+
+/* The caller should hold cpuset_mutex */
 void dl_add_task_root_domain(struct task_struct *p)
 {
 	struct rq_flags rf;
 	struct rq *rq;
 	struct dl_bw *dl_b;
+	unsigned int cpu;
+	struct cpumask *msk = this_cpu_cpumask_var_ptr(local_cpu_mask_dl);
 
 	raw_spin_lock_irqsave(&p->pi_lock, rf.flags);
 	if (!dl_task(p) || dl_entity_is_special(&p->dl)) {
@@ -2919,16 +2952,25 @@ void dl_add_task_root_domain(struct task_struct *p)
 		return;
 	}
 
-	rq = __task_rq_lock(p, &rf);
-
+	/*
+	 * Get an active rq, whose rq->rd traces the correct root
+	 * domain.
+	 * Ideally this would be under cpuset reader lock until rq->rd is
+	 * fetched.  However, sleepable locks cannot nest inside pi_lock, so we
+	 * rely on the caller of dl_add_task_root_domain() holds 'cpuset_mutex'
+	 * to guarantee the CPU stays in the cpuset.
+	 */
+	dl_get_task_effective_cpus(p, msk);
+	cpu = cpumask_first_and(cpu_active_mask, msk);
+	BUG_ON(cpu >= nr_cpu_ids);
+	rq = cpu_rq(cpu);
 	dl_b = &rq->rd->dl_bw;
-	raw_spin_lock(&dl_b->lock);
+	/* End of fetching rd */
 
+	raw_spin_lock(&dl_b->lock);
 	__dl_add(dl_b, p->dl.dl_bw, cpumask_weight(rq->rd->span));
-
 	raw_spin_unlock(&dl_b->lock);
-
-	task_rq_unlock(rq, p, &rf);
+	raw_spin_unlock_irqrestore(&p->pi_lock, rf.flags);
 }
 
 void dl_clear_root_domain(struct root_domain *rd)
-- 
2.49.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCHv6 2/2] sched/deadline: Walk up cpuset hierarchy to decide root domain when hot-unplug
  2025-11-17  9:27 ` [PATCHv6 2/2] sched/deadline: Walk up cpuset hierarchy to decide root domain when hot-unplug Pingfan Liu
@ 2025-11-17 11:00   ` kernel test robot
  2025-11-17 11:00   ` kernel test robot
  1 sibling, 0 replies; 8+ messages in thread
From: kernel test robot @ 2025-11-17 11:00 UTC (permalink / raw)
  To: Pingfan Liu, linux-kernel
  Cc: oe-kbuild-all, Pingfan Liu, Waiman Long, Chen Ridong,
	Peter Zijlstra, Juri Lelli, Pierre Gondois, Ingo Molnar,
	Vincent Guittot, Dietmar Eggemann, Steven Rostedt, Ben Segall,
	Mel Gorman, Valentin Schneider, Tejun Heo, Johannes Weiner,
	mkoutny

Hi Pingfan,

kernel test robot noticed the following build errors:

[auto build test ERROR on tj-cgroup/for-next]
[also build test ERROR on tip/sched/core peterz-queue/sched/core linus/master v6.18-rc6 next-20251114]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Pingfan-Liu/cgroup-cpuset-Introduce-cpuset_cpus_allowed_locked/20251117-173841
base:   https://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git for-next
patch link:    https://lore.kernel.org/r/20251117092732.16419-3-piliu%40redhat.com
patch subject: [PATCHv6 2/2] sched/deadline: Walk up cpuset hierarchy to decide root domain when hot-unplug
config: nios2-allnoconfig (https://download.01.org/0day-ci/archive/20251117/202511171843.cLkhUJ9Q-lkp@intel.com/config)
compiler: nios2-linux-gcc (GCC) 11.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251117/202511171843.cLkhUJ9Q-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511171843.cLkhUJ9Q-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from kernel/sched/build_policy.c:58:
   kernel/sched/deadline.c: In function 'dl_get_task_effective_cpus':
>> kernel/sched/deadline.c:2937:9: error: implicit declaration of function 'cpuset_cpus_allowed_locked'; did you mean 'cpuset_cpus_allowed_fallback'? [-Werror=implicit-function-declaration]
    2937 |         cpuset_cpus_allowed_locked(p, cpus);
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~
         |         cpuset_cpus_allowed_fallback
   cc1: some warnings being treated as errors


vim +2937 kernel/sched/deadline.c

  2910	
  2911	/*
  2912	 * This function always returns a non-empty bitmap in @cpus. This is because
  2913	 * if a root domain has reserved bandwidth for DL tasks, the DL bandwidth
  2914	 * check will prevent CPU hotplug from deactivating all CPUs in that domain.
  2915	 */
  2916	static void dl_get_task_effective_cpus(struct task_struct *p, struct cpumask *cpus)
  2917	{
  2918		const struct cpumask *hk_msk;
  2919	
  2920		hk_msk = housekeeping_cpumask(HK_TYPE_DOMAIN);
  2921		if (housekeeping_enabled(HK_TYPE_DOMAIN)) {
  2922			if (!cpumask_intersects(p->cpus_ptr, hk_msk)) {
  2923				/*
  2924				 * CPUs isolated by isolcpu="domain" always belong to
  2925				 * def_root_domain.
  2926				 */
  2927				cpumask_andnot(cpus, cpu_active_mask, hk_msk);
  2928				return;
  2929			}
  2930		}
  2931	
  2932		/*
  2933		 * If a root domain holds a DL task, it must have active CPUs. So
  2934		 * active CPUs can always be found by walking up the task's cpuset
  2935		 * hierarchy up to the partition root.
  2936		 */
> 2937		cpuset_cpus_allowed_locked(p, cpus);
  2938	}
  2939	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCHv6 2/2] sched/deadline: Walk up cpuset hierarchy to decide root domain when hot-unplug
  2025-11-17  9:27 ` [PATCHv6 2/2] sched/deadline: Walk up cpuset hierarchy to decide root domain when hot-unplug Pingfan Liu
  2025-11-17 11:00   ` kernel test robot
@ 2025-11-17 11:00   ` kernel test robot
  1 sibling, 0 replies; 8+ messages in thread
From: kernel test robot @ 2025-11-17 11:00 UTC (permalink / raw)
  To: Pingfan Liu, linux-kernel
  Cc: llvm, oe-kbuild-all, Pingfan Liu, Waiman Long, Chen Ridong,
	Peter Zijlstra, Juri Lelli, Pierre Gondois, Ingo Molnar,
	Vincent Guittot, Dietmar Eggemann, Steven Rostedt, Ben Segall,
	Mel Gorman, Valentin Schneider, Tejun Heo, Johannes Weiner,
	mkoutny

Hi Pingfan,

kernel test robot noticed the following build errors:

[auto build test ERROR on tj-cgroup/for-next]
[also build test ERROR on tip/sched/core peterz-queue/sched/core linus/master v6.18-rc6 next-20251114]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Pingfan-Liu/cgroup-cpuset-Introduce-cpuset_cpus_allowed_locked/20251117-173841
base:   https://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git for-next
patch link:    https://lore.kernel.org/r/20251117092732.16419-3-piliu%40redhat.com
patch subject: [PATCHv6 2/2] sched/deadline: Walk up cpuset hierarchy to decide root domain when hot-unplug
config: x86_64-allnoconfig (https://download.01.org/0day-ci/archive/20251117/202511171845.tuNk3Eb6-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251117/202511171845.tuNk3Eb6-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511171845.tuNk3Eb6-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from kernel/sched/build_policy.c:58:
>> kernel/sched/deadline.c:2937:2: error: call to undeclared function 'cpuset_cpus_allowed_locked'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
    2937 |         cpuset_cpus_allowed_locked(p, cpus);
         |         ^
   1 error generated.


vim +/cpuset_cpus_allowed_locked +2937 kernel/sched/deadline.c

  2910	
  2911	/*
  2912	 * This function always returns a non-empty bitmap in @cpus. This is because
  2913	 * if a root domain has reserved bandwidth for DL tasks, the DL bandwidth
  2914	 * check will prevent CPU hotplug from deactivating all CPUs in that domain.
  2915	 */
  2916	static void dl_get_task_effective_cpus(struct task_struct *p, struct cpumask *cpus)
  2917	{
  2918		const struct cpumask *hk_msk;
  2919	
  2920		hk_msk = housekeeping_cpumask(HK_TYPE_DOMAIN);
  2921		if (housekeeping_enabled(HK_TYPE_DOMAIN)) {
  2922			if (!cpumask_intersects(p->cpus_ptr, hk_msk)) {
  2923				/*
  2924				 * CPUs isolated by isolcpu="domain" always belong to
  2925				 * def_root_domain.
  2926				 */
  2927				cpumask_andnot(cpus, cpu_active_mask, hk_msk);
  2928				return;
  2929			}
  2930		}
  2931	
  2932		/*
  2933		 * If a root domain holds a DL task, it must have active CPUs. So
  2934		 * active CPUs can always be found by walking up the task's cpuset
  2935		 * hierarchy up to the partition root.
  2936		 */
> 2937		cpuset_cpus_allowed_locked(p, cpus);
  2938	}
  2939	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCHv6 1/2] cgroup/cpuset: Introduce cpuset_cpus_allowed_locked()
  2025-11-17  9:27 ` [PATCHv6 1/2] cgroup/cpuset: Introduce cpuset_cpus_allowed_locked() Pingfan Liu
@ 2025-11-17 20:37   ` Waiman Long
  2025-11-18  6:30     ` Pingfan Liu
  0 siblings, 1 reply; 8+ messages in thread
From: Waiman Long @ 2025-11-17 20:37 UTC (permalink / raw)
  To: Pingfan Liu, cgroups
  Cc: Chen Ridong, Peter Zijlstra, Juri Lelli, Pierre Gondois,
	Ingo Molnar, Vincent Guittot, Dietmar Eggemann, Steven Rostedt,
	Ben Segall, Mel Gorman, Valentin Schneider, Tejun Heo,
	Johannes Weiner, mkoutny, linux-kernel

On 11/17/25 4:27 AM, Pingfan Liu wrote:
> cpuset_cpus_allowed() uses a reader lock that is sleepable under RT,
> which means it cannot be called inside raw_spin_lock_t context.
>
> Introduce a new cpuset_cpus_allowed_locked() helper that performs the
> same function as cpuset_cpus_allowed() except that the caller must have
> acquired the cpuset_mutex so that no further locking will be needed.
>
> Suggested-by: Waiman Long <longman@redhat.com>
> Signed-off-by: Pingfan Liu <piliu@redhat.com>
> Cc: Waiman Long <longman@redhat.com>
> Cc: Tejun Heo <tj@kernel.org>
> Cc: Johannes Weiner <hannes@cmpxchg.org>
> Cc: "Michal Koutný" <mkoutny@suse.com>
> Cc: linux-kernel@vger.kernel.org
> To: cgroups@vger.kernel.org
> ---
>   include/linux/cpuset.h |  1 +
>   kernel/cgroup/cpuset.c | 51 +++++++++++++++++++++++++++++-------------
>   2 files changed, 37 insertions(+), 15 deletions(-)
>
> diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
> index 2ddb256187b51..e057a3123791e 100644
> --- a/include/linux/cpuset.h
> +++ b/include/linux/cpuset.h
> @@ -75,6 +75,7 @@ extern void dec_dl_tasks_cs(struct task_struct *task);
>   extern void cpuset_lock(void);
>   extern void cpuset_unlock(void);
>   extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask);
> +extern void cpuset_cpus_allowed_locked(struct task_struct *p, struct cpumask *mask);
>   extern bool cpuset_cpus_allowed_fallback(struct task_struct *p);
>   extern bool cpuset_cpu_is_isolated(int cpu);
>   extern nodemask_t cpuset_mems_allowed(struct task_struct *p);

Ah, the following code should be added to to !CONFIG_CPUSETS section 
after cpuset_cpus_allowed().

#define cpuset_cpus_allowed_locked(p, m)  cpuset_cpus_allowed(p, m)

Or you can add another inline function that just calls 
cpuset_cpus_allowed().

Cheers,
Longman


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCHv6 1/2] cgroup/cpuset: Introduce cpuset_cpus_allowed_locked()
  2025-11-17 20:37   ` Waiman Long
@ 2025-11-18  6:30     ` Pingfan Liu
  2025-11-18 14:33       ` Waiman Long
  0 siblings, 1 reply; 8+ messages in thread
From: Pingfan Liu @ 2025-11-18  6:30 UTC (permalink / raw)
  To: Waiman Long
  Cc: cgroups, Chen Ridong, Peter Zijlstra, Juri Lelli, Pierre Gondois,
	Ingo Molnar, Vincent Guittot, Dietmar Eggemann, Steven Rostedt,
	Ben Segall, Mel Gorman, Valentin Schneider, Tejun Heo,
	Johannes Weiner, mkoutny, linux-kernel

On Tue, Nov 18, 2025 at 4:37 AM Waiman Long <llong@redhat.com> wrote:
>
> On 11/17/25 4:27 AM, Pingfan Liu wrote:
> > cpuset_cpus_allowed() uses a reader lock that is sleepable under RT,
> > which means it cannot be called inside raw_spin_lock_t context.
> >
> > Introduce a new cpuset_cpus_allowed_locked() helper that performs the
> > same function as cpuset_cpus_allowed() except that the caller must have
> > acquired the cpuset_mutex so that no further locking will be needed.
> >
> > Suggested-by: Waiman Long <longman@redhat.com>
> > Signed-off-by: Pingfan Liu <piliu@redhat.com>
> > Cc: Waiman Long <longman@redhat.com>
> > Cc: Tejun Heo <tj@kernel.org>
> > Cc: Johannes Weiner <hannes@cmpxchg.org>
> > Cc: "Michal Koutný" <mkoutny@suse.com>
> > Cc: linux-kernel@vger.kernel.org
> > To: cgroups@vger.kernel.org
> > ---
> >   include/linux/cpuset.h |  1 +
> >   kernel/cgroup/cpuset.c | 51 +++++++++++++++++++++++++++++-------------
> >   2 files changed, 37 insertions(+), 15 deletions(-)
> >
> > diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
> > index 2ddb256187b51..e057a3123791e 100644
> > --- a/include/linux/cpuset.h
> > +++ b/include/linux/cpuset.h
> > @@ -75,6 +75,7 @@ extern void dec_dl_tasks_cs(struct task_struct *task);
> >   extern void cpuset_lock(void);
> >   extern void cpuset_unlock(void);
> >   extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask);
> > +extern void cpuset_cpus_allowed_locked(struct task_struct *p, struct cpumask *mask);
> >   extern bool cpuset_cpus_allowed_fallback(struct task_struct *p);
> >   extern bool cpuset_cpu_is_isolated(int cpu);
> >   extern nodemask_t cpuset_mems_allowed(struct task_struct *p);
>
> Ah, the following code should be added to to !CONFIG_CPUSETS section
> after cpuset_cpus_allowed().
>
> #define cpuset_cpus_allowed_locked(p, m)  cpuset_cpus_allowed(p, m)
>
> Or you can add another inline function that just calls
> cpuset_cpus_allowed().
>

It may be better to make cpuset_cpus_allowed() call
cpuset_cpus_allowed_locked(), following the call chain used under
CONFIG_CPUSETS case.

Thanks,

Pingfan


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCHv6 1/2] cgroup/cpuset: Introduce cpuset_cpus_allowed_locked()
  2025-11-18  6:30     ` Pingfan Liu
@ 2025-11-18 14:33       ` Waiman Long
  0 siblings, 0 replies; 8+ messages in thread
From: Waiman Long @ 2025-11-18 14:33 UTC (permalink / raw)
  To: Pingfan Liu, Waiman Long
  Cc: cgroups, Chen Ridong, Peter Zijlstra, Juri Lelli, Pierre Gondois,
	Ingo Molnar, Vincent Guittot, Dietmar Eggemann, Steven Rostedt,
	Ben Segall, Mel Gorman, Valentin Schneider, Tejun Heo,
	Johannes Weiner, mkoutny, linux-kernel

On 11/18/25 1:30 AM, Pingfan Liu wrote:
> On Tue, Nov 18, 2025 at 4:37 AM Waiman Long <llong@redhat.com> wrote:
>> On 11/17/25 4:27 AM, Pingfan Liu wrote:
>>> cpuset_cpus_allowed() uses a reader lock that is sleepable under RT,
>>> which means it cannot be called inside raw_spin_lock_t context.
>>>
>>> Introduce a new cpuset_cpus_allowed_locked() helper that performs the
>>> same function as cpuset_cpus_allowed() except that the caller must have
>>> acquired the cpuset_mutex so that no further locking will be needed.
>>>
>>> Suggested-by: Waiman Long <longman@redhat.com>
>>> Signed-off-by: Pingfan Liu <piliu@redhat.com>
>>> Cc: Waiman Long <longman@redhat.com>
>>> Cc: Tejun Heo <tj@kernel.org>
>>> Cc: Johannes Weiner <hannes@cmpxchg.org>
>>> Cc: "Michal Koutný" <mkoutny@suse.com>
>>> Cc: linux-kernel@vger.kernel.org
>>> To: cgroups@vger.kernel.org
>>> ---
>>>    include/linux/cpuset.h |  1 +
>>>    kernel/cgroup/cpuset.c | 51 +++++++++++++++++++++++++++++-------------
>>>    2 files changed, 37 insertions(+), 15 deletions(-)
>>>
>>> diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
>>> index 2ddb256187b51..e057a3123791e 100644
>>> --- a/include/linux/cpuset.h
>>> +++ b/include/linux/cpuset.h
>>> @@ -75,6 +75,7 @@ extern void dec_dl_tasks_cs(struct task_struct *task);
>>>    extern void cpuset_lock(void);
>>>    extern void cpuset_unlock(void);
>>>    extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask);
>>> +extern void cpuset_cpus_allowed_locked(struct task_struct *p, struct cpumask *mask);
>>>    extern bool cpuset_cpus_allowed_fallback(struct task_struct *p);
>>>    extern bool cpuset_cpu_is_isolated(int cpu);
>>>    extern nodemask_t cpuset_mems_allowed(struct task_struct *p);
>> Ah, the following code should be added to to !CONFIG_CPUSETS section
>> after cpuset_cpus_allowed().
>>
>> #define cpuset_cpus_allowed_locked(p, m)  cpuset_cpus_allowed(p, m)
>>
>> Or you can add another inline function that just calls
>> cpuset_cpus_allowed().
>>
> It may be better to make cpuset_cpus_allowed() call
> cpuset_cpus_allowed_locked(), following the call chain used under
> CONFIG_CPUSETS case.

That is fine too.

Cheers,
Longman

>
> Thanks,
>
> Pingfan
>


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2025-11-18 14:33 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-11-17  9:27 [PATCHv6 0/2] sched/deadline: Walk up cpuset hierarchy to decide root domain when hot-unplug Pingfan Liu
2025-11-17  9:27 ` [PATCHv6 1/2] cgroup/cpuset: Introduce cpuset_cpus_allowed_locked() Pingfan Liu
2025-11-17 20:37   ` Waiman Long
2025-11-18  6:30     ` Pingfan Liu
2025-11-18 14:33       ` Waiman Long
2025-11-17  9:27 ` [PATCHv6 2/2] sched/deadline: Walk up cpuset hierarchy to decide root domain when hot-unplug Pingfan Liu
2025-11-17 11:00   ` kernel test robot
2025-11-17 11:00   ` kernel test robot

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

all inboxes | Powered by JetHome®