[peterz-queue:sched/hackery 6/7] kernel/sched/fair.c:13490:4: warning: releasing raw_spinlock 'rq_lockp(this_rq)' that was not held

kernel test robot <[email protected]>
Newsgroups dev.linux.lists.llvm,dev.linux.lists.oe-kbuild-all
Message-ID <[email protected]>
tree:   https://git.kernel.org/pub/scm/linux/kernel/git/peterz/queue.git sched/hackery
head:   312c23a8d476a8f31cad58181b12950e9662a45c
commit: 65c5833b169f85988d1f1f48726c3554a92c7884 [6/7] sched/fair: Push sched_balance_newidle() unlock down
config: arm-randconfig-004-20260822 (https://download.01.org/0day-ci/archive/20260822/[email protected]/config)
compiler: clang version 24.0.0git (https://github.com/llvm/llvm-project 935bfc708590c60147a79c7df145bb6e68b1d388)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260822/[email protected]/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 <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

>> kernel/sched/fair.c:13490:4: warning: releasing raw_spinlock 'rq_lockp(this_rq)' that was not held [-Wthread-safety-analysis]
    13490 |                         raw_spin_rq_unlock(this_rq);
          |                         ^
   kernel/sched/fair.c:13624:3: warning: releasing raw_spinlock 'rq_lockp(this_rq)' that was not held [-Wthread-safety-analysis]
    13624 |                 raw_spin_rq_unlock(this_rq);
          |                 ^
>> kernel/sched/fair.c:13725:9: warning: raw_spinlock 'rq_lockp(this_rq)' is not held on every path through here [-Wthread-safety-analysis]
    13725 |         return ld_moved;
          |                ^
   kernel/sched/fair.c:13723:3: note: raw_spinlock acquired here
    13723 |                 raw_spin_rq_lock(this_rq);
          |                 ^
   3 warnings generated.


vim +13490 kernel/sched/fair.c

 13411	
 13412	/*
 13413	 * Check this_cpu to ensure it is balanced within domain. Attempt to move
 13414	 * tasks if there is an imbalance.
 13415	 */
 13416	static int sched_balance_rq(int this_cpu, struct rq *this_rq,
 13417				struct sched_domain *sd, enum cpu_idle_type idle,
 13418				int *continue_balancing)
 13419	{
 13420		bool lock_rq = false, unlock_rq = idle == CPU_NEWLY_IDLE;
 13421		int ld_moved, cur_ld_moved, active_balance = 0;
 13422		struct sched_domain *sd_parent = sd->parent;
 13423		struct sched_group *group;
 13424		struct rq *busiest;
 13425		struct rq_flags rf;
 13426		struct cpumask *cpus = this_cpu_cpumask_var_ptr(load_balance_mask);
 13427		struct lb_env env = {
 13428			.sd		= sd,
 13429			.dst_cpu	= this_cpu,
 13430			.dst_rq		= this_rq,
 13431			.dst_grpmask    = group_balance_mask(sd->groups),
 13432			.idle		= idle,
 13433			.loop_break	= SCHED_NR_MIGRATE_BREAK,
 13434			.cpus		= cpus,
 13435			.fbq_type	= all,
 13436			.tasks		= LIST_HEAD_INIT(env.tasks),
 13437		};
 13438		bool need_unlock = false;
 13439	
 13440		cpumask_and(cpus, sched_domain_span(sd), cpu_active_mask);
 13441	
 13442		schedstat_inc(sd->lb_count[idle]);
 13443	
 13444	redo:
 13445		if (!should_we_balance(&env)) {
 13446			*continue_balancing = 0;
 13447			goto out_balanced;
 13448		}
 13449	
 13450		if (!need_unlock && (sd->flags & SD_SERIALIZE)) {
 13451			int zero = 0;
 13452			if (!atomic_try_cmpxchg_acquire(&sched_balance_running, &zero, 1))
 13453				goto out_balanced;
 13454	
 13455			need_unlock = true;
 13456		}
 13457	
 13458		group = sched_balance_find_src_group(&env);
 13459		if (!group) {
 13460			schedstat_inc(sd->lb_nobusyg[idle]);
 13461			goto out_balanced;
 13462		}
 13463	
 13464		busiest = sched_balance_find_src_rq(&env, group);
 13465		if (!busiest) {
 13466			schedstat_inc(sd->lb_nobusyq[idle]);
 13467			goto out_balanced;
 13468		}
 13469	
 13470		WARN_ON_ONCE(busiest == env.dst_rq);
 13471	
 13472		update_lb_imbalance_stat(&env, sd, idle);
 13473	
 13474		env.src_cpu = busiest->cpu;
 13475		env.src_rq = busiest;
 13476	
 13477		ld_moved = 0;
 13478		/* Clear this flag as soon as we find a pullable task */
 13479		env.flags |= LBF_ALL_PINNED;
 13480		if (busiest->nr_running > 1) {
 13481			/*
 13482			 * Attempt to move tasks. If sched_balance_find_src_group has found
 13483			 * an imbalance but busiest->nr_running <= 1, the group is
 13484			 * still unbalanced. ld_moved simply stays zero, so it is
 13485			 * correctly treated as an imbalance.
 13486			 */
 13487			env.loop_max  = min(sysctl_sched_nr_migrate, busiest->nr_running);
 13488	
 13489			if (unlock_rq) {
 13490				raw_spin_rq_unlock(this_rq);
 13491				unlock_rq = false;
 13492				lock_rq = true;
 13493			}
 13494	
 13495	more_balance:
 13496			rq_lock_irqsave(busiest, &rf);
 13497			update_rq_clock(busiest);
 13498	
 13499			/*
 13500			 * cur_ld_moved - load moved in current iteration
 13501			 * ld_moved     - cumulative load moved across iterations
 13502			 */
 13503			cur_ld_moved = detach_tasks(&env);
 13504	
 13505			/*
 13506			 * We've detached some tasks from busiest_rq. Every
 13507			 * task is masked "TASK_ON_RQ_MIGRATING", so we can safely
 13508			 * unlock busiest->lock, and we are able to be sure
 13509			 * that nobody can manipulate the tasks in parallel.
 13510			 * See task_rq_lock() family for the details.
 13511			 */
 13512	
 13513			rq_unlock(busiest, &rf);
 13514	
 13515			if (cur_ld_moved) {
 13516				attach_tasks(&env);
 13517				ld_moved += cur_ld_moved;
 13518			}
 13519	
 13520			local_irq_restore(rf.flags);
 13521	
 13522			if (env.flags & LBF_NEED_BREAK) {
 13523				env.flags &= ~LBF_NEED_BREAK;
 13524				goto more_balance;
 13525			}
 13526	
 13527			/*
 13528			 * Revisit (affine) tasks on src_cpu that couldn't be moved to
 13529			 * us and move them to an alternate dst_cpu in our sched_group
 13530			 * where they can run. The upper limit on how many times we
 13531			 * iterate on same src_cpu is dependent on number of CPUs in our
 13532			 * sched_group.
 13533			 *
 13534			 * This changes load balance semantics a bit on who can move
 13535			 * load to a given_cpu. In addition to the given_cpu itself
 13536			 * (or a ilb_cpu acting on its behalf where given_cpu is
 13537			 * nohz-idle), we now have balance_cpu in a position to move
 13538			 * load to given_cpu. In rare situations, this may cause
 13539			 * conflicts (balance_cpu and given_cpu/ilb_cpu deciding
 13540			 * _independently_ and at _same_ time to move some load to
 13541			 * given_cpu) causing excess load to be moved to given_cpu.
 13542			 * This however should not happen so much in practice and
 13543			 * moreover subsequent load balance cycles should correct the
 13544			 * excess load moved.
 13545			 */
 13546			if ((env.flags & LBF_DST_PINNED) && env.imbalance > 0) {
 13547	
 13548				/* Prevent to re-select dst_cpu via env's CPUs */
 13549				__cpumask_clear_cpu(env.dst_cpu, env.cpus);
 13550	
 13551				env.dst_rq	 = cpu_rq(env.new_dst_cpu);
 13552				env.dst_cpu	 = env.new_dst_cpu;
 13553				env.flags	&= ~LBF_DST_PINNED;
 13554				env.loop	 = 0;
 13555				env.loop_break	 = SCHED_NR_MIGRATE_BREAK;
 13556	
 13557				/*
 13558				 * Go back to "more_balance" rather than "redo" since we
 13559				 * need to continue with same src_cpu.
 13560				 */
 13561				goto more_balance;
 13562			}
 13563	
 13564			/*
 13565			 * We failed to reach balance because of affinity.
 13566			 */
 13567			if (sd_parent) {
 13568				int *group_imbalance = &sd_parent->groups->sgc->imbalance;
 13569	
 13570				if ((env.flags & LBF_SOME_PINNED) && env.imbalance > 0)
 13571					*group_imbalance = 1;
 13572			}
 13573	
 13574			/* All tasks on this runqueue were pinned by CPU affinity */
 13575			if (unlikely(env.flags & LBF_ALL_PINNED)) {
 13576				__cpumask_clear_cpu(cpu_of(busiest), cpus);
 13577				/*
 13578				 * Attempting to continue load balancing at the current
 13579				 * sched_domain level only makes sense if there are
 13580				 * active CPUs remaining as possible busiest CPUs to
 13581				 * pull load from which are not contained within the
 13582				 * destination group that is receiving any migrated
 13583				 * load.
 13584				 */
 13585				if (!cpumask_subset(cpus, env.dst_grpmask)) {
 13586					env.loop = 0;
 13587					env.loop_break = SCHED_NR_MIGRATE_BREAK;
 13588					goto redo;
 13589				}
 13590				goto out_all_pinned;
 13591			}
 13592		}
 13593	
 13594		if (ld_moved) {
 13595			sd->nr_balance_failed = 0;
 13596			goto out_unbalanced;
 13597		}
 13598	
 13599		schedstat_inc(sd->lb_failed[idle]);
 13600		/*
 13601		 * Increment the failure counter only on periodic balance.
 13602		 * We do not want newidle balance, which can be very
 13603		 * frequent, pollute the failure counter causing
 13604		 * excessive cache_hot migrations and active balances.
 13605		 *
 13606		 * Similarly for migration_misfit which is not related to
 13607		 * load/util migration, don't pollute nr_balance_failed.
 13608		 *
 13609		 * The same for cache aware scheduling's allowance for
 13610		 * load imbalance. If regular load balance does not
 13611		 * migrate task due to LLC locality, it is a expected
 13612		 * behavior and don't pollute nr_balance_failed.
 13613		 * See can_migrate_task().
 13614		 */
 13615		if (idle != CPU_NEWLY_IDLE &&
 13616		    env.migration_type != migrate_misfit &&
 13617		    !(env.flags & LBF_LLC_PINNED))
 13618			sd->nr_balance_failed++;
 13619	
 13620		if (!need_active_balance(&env))
 13621			goto out_unbalanced;
 13622	
 13623		if (unlock_rq) {
 13624			raw_spin_rq_unlock(this_rq);
 13625			unlock_rq = false;
 13626			lock_rq = true;
 13627		}
 13628	
 13629		scoped_guard (raw_spin_rq_lock_irqsave, busiest) {
 13630			/*
 13631			 * Don't kick the active_load_balance_cpu_stop,
 13632			 * if the curr task on busiest CPU can't be
 13633			 * moved to this_cpu:
 13634			 */
 13635			if (!cpumask_test_cpu(this_cpu, busiest->curr->cpus_ptr))
 13636				goto out_one_pinned;
 13637	
 13638			/* Record that we found at least one task that could run on this_cpu */
 13639			env.flags &= ~LBF_ALL_PINNED;
 13640	
 13641			/*
 13642			 * ->active_balance synchronizes accesses to
 13643			 * ->active_balance_work.  Once set, it's cleared
 13644			 * only after active load balance is finished.
 13645			 */
 13646			if (busiest->active_balance)
 13647				goto out_unbalanced;
 13648	
 13649			/*
 13650			 * @busiest dropped its rq_lock in the middle of
 13651			 * scheduling out its ->curr task (->on_rq := 0), no
 13652			 * need to forcefully punt it away with active balance.
 13653			 */
 13654			if (!busiest->curr->on_rq)
 13655				goto out_unbalanced;
 13656	
 13657			busiest->active_balance = 1;
 13658			busiest->push_cpu = this_cpu;
 13659			active_balance = 1;
 13660			preempt_disable();
 13661		}
 13662		if (active_balance) {
 13663			stop_one_cpu_nowait(cpu_of(busiest),
 13664					    active_load_balance_cpu_stop, busiest,
 13665					    &busiest->active_balance_work);
 13666		}
 13667		preempt_enable();
 13668	
 13669	out_unbalanced:
 13670		/* We were unbalanced, so reset the balancing interval */
 13671		sd->balance_interval = sd->min_interval;
 13672		goto out;
 13673	
 13674	out_balanced:
 13675		/*
 13676		 * We reach balance although we may have faced some affinity
 13677		 * constraints. Clear the imbalance flag only if other tasks got
 13678		 * a chance to move and fix the imbalance.
 13679		 */
 13680		if (sd_parent && !(env.flags & LBF_ALL_PINNED)) {
 13681			int *group_imbalance = &sd_parent->groups->sgc->imbalance;
 13682	
 13683			if (*group_imbalance)
 13684				*group_imbalance = 0;
 13685		}
 13686	
 13687	out_all_pinned:
 13688		/*
 13689		 * We reach balance because all tasks are pinned at this level so
 13690		 * we can't migrate them. Let the imbalance flag set so parent level
 13691		 * can try to migrate them.
 13692		 */
 13693		schedstat_inc(sd->lb_balanced[idle]);
 13694	
 13695		sd->nr_balance_failed = 0;
 13696	
 13697	out_one_pinned:
 13698		ld_moved = 0;
 13699	
 13700		/*
 13701		 * sched_balance_newidle() disregards balance intervals, so we could
 13702		 * repeatedly reach this code, which would lead to balance_interval
 13703		 * skyrocketing in a short amount of time. Skip the balance_interval
 13704		 * increase logic to avoid that.
 13705		 *
 13706		 * Similarly misfit migration which is not necessarily an indication of
 13707		 * the system being busy and requires lb to backoff to let it settle
 13708		 * down.
 13709		 */
 13710		if (env.idle == CPU_NEWLY_IDLE ||
 13711		    env.migration_type == migrate_misfit)
 13712			goto out;
 13713	
 13714		/* tune up the balancing interval */
 13715		if ((env.flags & LBF_ALL_PINNED &&
 13716		     sd->balance_interval < MAX_PINNED_INTERVAL) ||
 13717		    sd->balance_interval < sd->max_interval)
 13718			sd->balance_interval *= 2;
 13719	out:
 13720		if (need_unlock)
 13721			atomic_set_release(&sched_balance_running, 0);
 13722		if (lock_rq)
 13723			raw_spin_rq_lock(this_rq);
 13724	
 13725		return ld_moved;
 13726	}
 13727	

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.