mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
scftorture: Remove preempt_disable() in scftorture_invoke_one()
The smp_call*() functions handle their required preemption and CPU pinning internally. The explicit preempt_disable() in scftorture_invoke_one() is therefore no longer required for correctness. Keeping the outer preempt_disable() would also prevent scftorture from exercising the narrowed internal preemption-disabled regions during IPI dispatch. Removing the outer preemption protection can expose a CPU hotplug race in the test validation when use_cpus_read_lock is false. For multicast operations, SCF_PRIM_MANY or SCF_PRIM_ALL, if only one CPU is online, smp_call_function_many() correctly skips sending IPIs and leaves scfc_out false. Without preemption disabled, a CPU hotplug thread can preempt the test thread, bring a second CPU online and increment num_online_cpus(). When the test thread resumes, the validation check can observe num_online_cpus() > 1 and falsely trigger the memory-ordering warning, leaking the scfcp structure. Remove the preempt_disable() and preempt_enable() pairs around the smp_call*() invocations in scftorture_invoke_one(). Restrict the num_online_cpus() > 1 validation to the use_cpus_read_lock=true case, where the CPU count is stable during the evaluation. Signed-off-by: Chuyi Zhou <zhouchuyi@bytedance.com> Signed-off-by: Thomas Gleixner <tglx@kernel.org> Tested-by: Paul E. McKenney <paulmck@kernel.org> Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Link: https://patch.msgid.link/20260709122933.4021501-10-zhouchuyi@bytedance.com
This commit is contained in:
committed by
Thomas Gleixner
parent
947c397f59
commit
99b49e02f9
+4
-9
@@ -348,6 +348,8 @@ static void scftorture_invoke_one(struct scf_statistics *scfp, struct torture_ra
|
||||
int ret = 0;
|
||||
struct scf_check *scfcp = NULL;
|
||||
struct scf_selector *scfsp = scf_sel_rand(trsp);
|
||||
bool is_single = (scfsp->scfs_prim == SCF_PRIM_SINGLE ||
|
||||
scfsp->scfs_prim == SCF_PRIM_SINGLE_RPC);
|
||||
|
||||
if (scfsp->scfs_prim == SCF_PRIM_SINGLE || scfsp->scfs_wait) {
|
||||
scfcp = kmalloc_obj(*scfcp, GFP_ATOMIC);
|
||||
@@ -364,8 +366,6 @@ static void scftorture_invoke_one(struct scf_statistics *scfp, struct torture_ra
|
||||
}
|
||||
if (use_cpus_read_lock)
|
||||
cpus_read_lock();
|
||||
else
|
||||
preempt_disable();
|
||||
switch (scfsp->scfs_prim) {
|
||||
case SCF_PRIM_RESCHED:
|
||||
if (IS_BUILTIN(CONFIG_SCF_TORTURE_TEST)) {
|
||||
@@ -411,13 +411,10 @@ static void scftorture_invoke_one(struct scf_statistics *scfp, struct torture_ra
|
||||
if (!ret) {
|
||||
if (use_cpus_read_lock)
|
||||
cpus_read_unlock();
|
||||
else
|
||||
preempt_enable();
|
||||
|
||||
wait_for_completion(&scfcp->scfc_completion);
|
||||
if (use_cpus_read_lock)
|
||||
cpus_read_lock();
|
||||
else
|
||||
preempt_disable();
|
||||
} else {
|
||||
scfp->n_single_rpc_ofl++;
|
||||
scf_add_to_free_list(scfcp);
|
||||
@@ -452,7 +449,7 @@ static void scftorture_invoke_one(struct scf_statistics *scfp, struct torture_ra
|
||||
scfcp->scfc_out = true;
|
||||
}
|
||||
if (scfcp && scfsp->scfs_wait) {
|
||||
if (WARN_ON_ONCE((num_online_cpus() > 1 || scfsp->scfs_prim == SCF_PRIM_SINGLE) &&
|
||||
if (WARN_ON_ONCE(((use_cpus_read_lock && num_online_cpus() > 1) || is_single) &&
|
||||
!scfcp->scfc_out)) {
|
||||
pr_warn("%s: Memory-ordering failure, scfs_prim: %d.\n", __func__, scfsp->scfs_prim);
|
||||
atomic_inc(&n_mb_out_errs); // Leak rather than trash!
|
||||
@@ -463,8 +460,6 @@ static void scftorture_invoke_one(struct scf_statistics *scfp, struct torture_ra
|
||||
}
|
||||
if (use_cpus_read_lock)
|
||||
cpus_read_unlock();
|
||||
else
|
||||
preempt_enable();
|
||||
if (allocfail)
|
||||
schedule_timeout_idle((1 + longwait) * HZ); // Let no-wait handlers complete.
|
||||
else if (!(torture_random(trsp) & 0xfff))
|
||||
|
||||
Reference in New Issue
Block a user