vm.stat_interval is exposed in seconds, but proc_dointvec_jiffies() currently accepts zero and negative values. In the current tree, writing 0 succeeds and leaves /proc/sys/vm/stat_interval at 0. vmstat_update() uses the stored jiffy interval directly when it requeues its delayed work, so a zero interval can drive excessive kworker CPU usage. Negative values are not meaningful either. Switch vm.stat_interval to a small custom sysctl handler that keeps the existing seconds-based userspace ABI while rejecting values below 1 and capping the upper bound at INT_MAX / HZ. Link: https://bugzilla.kernel.org/show_bug.cgi?id=220226 Signed-off-by: Cao Ruichuang --- mm/vmstat.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/mm/vmstat.c b/mm/vmstat.c index 86b14b0f77b..f48d3bdad64 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -1964,6 +1964,7 @@ static const struct seq_operations vmstat_op = { #ifdef CONFIG_SMP static DEFINE_PER_CPU(struct delayed_work, vmstat_work); static int sysctl_stat_interval __read_mostly = HZ; +static const int sysctl_stat_interval_max = INT_MAX / HZ; static int vmstat_late_init_done; #ifdef CONFIG_PROC_FS @@ -1972,6 +1973,26 @@ static void refresh_vm_stats(struct work_struct *work) refresh_cpu_vm_stats(true); } +static int vmstat_stat_interval_handler(const struct ctl_table *table, int write, + void *buffer, size_t *lenp, loff_t *ppos) +{ + int interval = sysctl_stat_interval / HZ; + const struct ctl_table tmp = { + .data = &interval, + .maxlen = sizeof(interval), + .mode = table->mode, + .extra1 = SYSCTL_ONE, + .extra2 = (void *)&sysctl_stat_interval_max, + }; + int ret; + + ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); + if (!ret && write) + sysctl_stat_interval = interval * HZ; + + return ret; +} + static int vmstat_refresh(const struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { @@ -2236,7 +2257,7 @@ static const struct ctl_table vmstat_table[] = { .data = &sysctl_stat_interval, .maxlen = sizeof(sysctl_stat_interval), .mode = 0644, - .proc_handler = proc_dointvec_jiffies, + .proc_handler = vmstat_stat_interval_handler, }, { .procname = "stat_refresh", -- 2.39.5 (Apple Git-154)