[PATCH v6 11/12] mm/vmstat: refresh stats remotely instead of via work item

From: Marcelo Tosatti
Date: Tue Mar 14 2023 - 15:02:20 EST


Refresh per-CPU stats remotely, instead of queueing
work items, for the stat_refresh procfs method.

This fixes sosreport hang (which uses vmstat_refresh) with
spinning SCHED_FIFO process.

Signed-off-by: Marcelo Tosatti <mtosatti@xxxxxxxxxx>

Index: linux-vmstat-remote/mm/vmstat.c
===================================================================
--- linux-vmstat-remote.orig/mm/vmstat.c
+++ linux-vmstat-remote/mm/vmstat.c
@@ -1901,11 +1901,20 @@ static DEFINE_PER_CPU(struct delayed_wor
int sysctl_stat_interval __read_mostly = HZ;

#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_HAVE_CMPXCHG_LOCAL
+static int refresh_all_vm_stats(void);
+#else
static void refresh_vm_stats(struct work_struct *work)
{
refresh_cpu_vm_stats(true);
}

+static int refresh_all_vm_stats(void)
+{
+ return schedule_on_each_cpu(refresh_vm_stats);
+}
+#endif
+
int vmstat_refresh(struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
@@ -1925,7 +1934,7 @@ int vmstat_refresh(struct ctl_table *tab
* transiently negative values, report an error here if any of
* the stats is negative, so we know to go looking for imbalance.
*/
- err = schedule_on_each_cpu(refresh_vm_stats);
+ err = refresh_all_vm_stats();
if (err)
return err;
for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) {
@@ -2045,7 +2054,7 @@ static DECLARE_DEFERRABLE_WORK(shepherd,

#ifdef CONFIG_HAVE_CMPXCHG_LOCAL
/* Flush counters remotely if CPU uses cmpxchg to update its per-CPU counters */
-static void vmstat_shepherd(struct work_struct *w)
+static int refresh_all_vm_stats(void)
{
int cpu;

@@ -2055,7 +2064,12 @@ static void vmstat_shepherd(struct work_
cond_resched();
}
cpus_read_unlock();
+ return 0;
+}

+static void vmstat_shepherd(struct work_struct *w)
+{
+ refresh_all_vm_stats();
schedule_delayed_work(&shepherd,
round_jiffies_relative(sysctl_stat_interval));
}