Commit d363ef66 authored by Zheng Zucheng's avatar Zheng Zucheng
Browse files

sched/rt: Fix rt_runtime leaks with cpu hotplug

hulk inclusion
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBHFLI



--------------------------------

When using cgroup rt_bandwidth with RT_RUNTIME_SHARE dynamic change,
if there are cpu hotplug and RT_RUNTIME_SHARE changing concurrently,
the warning in __disable_runtime may occur:
WARNING: CPU: 1 PID: 1434 at kernel/sched/rt.c:806 __disable_runtime+0x354/0x370
RIP: 0010:__disable_runtime+0x354/0x370
Call Trace:
  ? __warn+0x9b/0x140
  ? __disable_runtime+0x354/0x370
  rq_offline_rt+0x3c/0x120
  set_rq_offline.part.0+0x3c/0xc0
  rq_attach_root+0x1e5/0x1f0
  cpu_attach_domain+0x1eb/0x250
  detach_destroy_domains+0xaf/0x1a0
  partition_sched_domains_locked+0x321/0x450
  rebuild_sched_domains_locked+0x16d/0x430
  ? generate_sched_domains+0x920/0x920
  cpuset_hotplug_workfn+0x451/0xe20
  ? cpuset_hotplug_update_tasks+0x530/0x530
  ? do_raw_spin_lock+0x1b0/0x1b0
  ? fill_page_cache_func+0xf0/0xf0
  process_one_work+0x4b2/0x8e0
  ? pwq_dec_nr_in_flight+0x100/0x100
  ? __list_add_valid+0x36/0xe0
  worker_thread+0x8b/0x580

The triggering scenario is as follows::
CPU0                                   CPU1
-----                                  -----

set_rq_offline(rq)
    __disable_runtime(rq) (1)
				      NO_RT_RUNTIME_SHARE
				      do_sched_rt_period_timer(2)
				      RT_RUNTIME_SHARE
				      do_balance_runtime  (3)

set_rq_online(rq)
    __enable_runtime(rq)  (4)

In step(1) rt_rq0->rt_runtime is set to RUNTIME_DISABLED, and this rt_rq's
runtime is not supposed to change until its rq gets online. However,
in step(2) timer trigger set rt_rq0->rt_runtime to rt_b->rt_runtime.
Then, in step(3) rt_rq0->rt_runtime is not RUNTIME_INF or RUNTIME_DISABLED,
so others can borrow rt_runtime from it. Finally, in
step(4) the rq gets online, so its rt_rq0's runtime is set to
rt_b->rt_runtime again, and since then the total rt_runtime in the domain
is increased by this way.
After these steps, when offline cpu and rebuild sched_domain
will offline all rq, and the last rq will find the rt_runtime is
increased but nowhere to return.

To fix this, when rt bandwidth timer expires, the rt_rq->rt_runtime of
offline CPU is not updated before online.

Fixes: 5cb5bd37 ("sched/rt: Fix rt_runtime leaks with cpu hotplug and RT_RUNTIME_SHARE")
Signed-off-by: default avatarZheng Zucheng <zhengzucheng@huawei.com>
parent 97f98c39
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -715,7 +715,8 @@ static void __disable_runtime(struct rq *rq)
		 * exactly the right amount of runtime to take out.
		 */
		if (rt_rq->rt_runtime == RUNTIME_INF ||
				rt_rq->rt_runtime == rt_b->rt_runtime)
		    rt_rq->rt_runtime == rt_b->rt_runtime ||
		    rt_rq->rt_runtime == RUNTIME_DISABLED)
			goto balanced;
		raw_spin_unlock(&rt_rq->rt_runtime_lock);

@@ -844,7 +845,9 @@ static int do_sched_rt_period_timer(struct rt_bandwidth *rt_b, int overrun)
		 * can be time-consuming. Try to avoid it when possible.
		 */
		raw_spin_lock(&rt_rq->rt_runtime_lock);
		if (!sched_feat(RT_RUNTIME_SHARE) && rt_rq->rt_runtime != RUNTIME_INF)
		if (!sched_feat(RT_RUNTIME_SHARE) &&
		    rt_rq->rt_runtime != RUNTIME_INF &&
		    rt_rq->rt_runtime != RUNTIME_DISABLED)
			rt_rq->rt_runtime = rt_b->rt_runtime;
		skip = !rt_rq->rt_time && !rt_rq->rt_nr_running;
		raw_spin_unlock(&rt_rq->rt_runtime_lock);
@@ -922,7 +925,7 @@ static int sched_rt_runtime_exceeded(struct rt_rq *rt_rq)

	balance_runtime(rt_rq);
	runtime = sched_rt_runtime(rt_rq);
	if (runtime == RUNTIME_INF)
	if (runtime == RUNTIME_INF || runtime == RUNTIME_DISABLED)
		return 0;

	if (rt_rq->rt_time > runtime) {
+1 −1
Original line number Diff line number Diff line
@@ -166,7 +166,7 @@ static inline void cpu_load_update_active(struct rq *this_rq) { }
/*
 * Single value that denotes runtime is disabled, and it should not be used.
 */
#define RUNTIME_DISABLED	(-2ULL)
#define RUNTIME_DISABLED	((u64)~1ULL)

static inline int idle_policy(int policy)
{