Skip to content

Commit 9fd8fcf

Browse files
lkpdnakpm00
authored andcommitted
vmstat: disable vmstat_work on vmstat_cpu_down_prep()
The upstream commit adcfb26 ("vmstat: disable vmstat_work on vmstat_cpu_down_prep()") introduced another warning during the boot phase so was soon reverted on upstream by commit cd6313b ("Revert "vmstat: disable vmstat_work on vmstat_cpu_down_prep()""). This commit resolves it and reattempts the original fix. Even after mm/vmstat:online teardown, shepherd may still queue work for the dying cpu until the cpu is removed from online mask. While it's quite rare, this means that after unbind_workers() unbinds a per-cpu kworker, it potentially runs vmstat_update for the dying CPU on an irrelevant cpu before entering atomic AP states. When CONFIG_DEBUG_PREEMPT=y, it results in the following error with the backtrace. BUG: using smp_processor_id() in preemptible [00000000] code: \ kworker/7:3/1702 caller is refresh_cpu_vm_stats+0x235/0x5f0 CPU: 0 UID: 0 PID: 1702 Comm: kworker/7:3 Tainted: G Tainted: [N]=TEST Workqueue: mm_percpu_wq vmstat_update Call Trace: <TASK> dump_stack_lvl+0x8d/0xb0 check_preemption_disabled+0xce/0xe0 refresh_cpu_vm_stats+0x235/0x5f0 vmstat_update+0x17/0xa0 process_one_work+0x869/0x1aa0 worker_thread+0x5e5/0x1100 kthread+0x29e/0x380 ret_from_fork+0x2d/0x70 ret_from_fork_asm+0x1a/0x30 </TASK> So, for mm/vmstat:online, disable vmstat_work reliably on teardown and symmetrically enable it on startup. For secondary CPUs during CPU hotplug scenarios, ensure the delayed work is disabled immediately after the initialization. These CPUs are not yet online when start_shepherd_timer() runs on boot CPU. vmstat_cpu_online() will enable the work for them. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Huacai Chen <[email protected]> Signed-off-by: Koichiro Den <[email protected]> Suggested-by: Huacai Chen <[email protected]> Tested-by: Charalampos Mitrodimas <[email protected]> Cc: Lorenzo Stoakes <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 212fe1c commit 9fd8fcf

File tree

1 file changed

+13
-2
lines changed

1 file changed

+13
-2
lines changed

mm/vmstat.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2122,10 +2122,20 @@ static void __init start_shepherd_timer(void)
21222122
{
21232123
int cpu;
21242124

2125-
for_each_possible_cpu(cpu)
2125+
for_each_possible_cpu(cpu) {
21262126
INIT_DEFERRABLE_WORK(per_cpu_ptr(&vmstat_work, cpu),
21272127
vmstat_update);
21282128

2129+
/*
2130+
* For secondary CPUs during CPU hotplug scenarios,
2131+
* vmstat_cpu_online() will enable the work.
2132+
* mm/vmstat:online enables and disables vmstat_work
2133+
* symmetrically during CPU hotplug events.
2134+
*/
2135+
if (!cpu_online(cpu))
2136+
disable_delayed_work_sync(&per_cpu(vmstat_work, cpu));
2137+
}
2138+
21292139
schedule_delayed_work(&shepherd,
21302140
round_jiffies_relative(sysctl_stat_interval));
21312141
}
@@ -2148,13 +2158,14 @@ static int vmstat_cpu_online(unsigned int cpu)
21482158
if (!node_state(cpu_to_node(cpu), N_CPU)) {
21492159
node_set_state(cpu_to_node(cpu), N_CPU);
21502160
}
2161+
enable_delayed_work(&per_cpu(vmstat_work, cpu));
21512162

21522163
return 0;
21532164
}
21542165

21552166
static int vmstat_cpu_down_prep(unsigned int cpu)
21562167
{
2157-
cancel_delayed_work_sync(&per_cpu(vmstat_work, cpu));
2168+
disable_delayed_work_sync(&per_cpu(vmstat_work, cpu));
21582169
return 0;
21592170
}
21602171

0 commit comments

Comments
 (0)