]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
mm/vmstat: refresh stats remotely instead of via work item
authorMarcelo Tosatti <mtosatti@redhat.com>
Mon, 20 Mar 2023 18:03:44 +0000 (15:03 -0300)
committerAndrew Morton <akpm@linux-foundation.org>
Wed, 5 Apr 2023 23:02:32 +0000 (16:02 -0700)
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.

Link: https://lkml.kernel.org/r/20230320180745.832991792@redhat.com
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Aaron Tomlin <atomlin@atomlin.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Frederic Weisbecker <frederic@kernel.org>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Huacai Chen <chenhuacai@kernel.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Peter Xu <peterx@redhat.com>
Cc: "Russell King (Oracle)" <linux@armlinux.org.uk>
Cc: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mm/vmstat.c

index 0a858e1c5fc6796d6c060acb5b181223b4c9df6e..9f1a8a162ff1ed61aa6bff5b294e080756ba3364 100644 (file)
@@ -1907,11 +1907,20 @@ static DEFINE_PER_CPU(struct delayed_work, vmstat_work);
 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)
 {
@@ -1931,7 +1940,7 @@ int vmstat_refresh(struct ctl_table *table, int write,
         * 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++) {
@@ -2051,7 +2060,7 @@ static DECLARE_DEFERRABLE_WORK(shepherd, vmstat_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;
 
@@ -2061,7 +2070,12 @@ static void vmstat_shepherd(struct work_struct *w)
                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));
 }