[PATCH -next] mm: make sure freeram is smaller than totalram

Yang Yingliang posted 1 patch 2 months, 1 week ago
include/linux/vmstat.h |  1 +
mm/show_mem.c          | 10 ++++++++++
mm/vmstat.c            | 15 ++++++++++-----
3 files changed, 21 insertions(+), 5 deletions(-)
[PATCH -next] mm: make sure freeram is smaller than totalram
Posted by Yang Yingliang 2 months, 1 week ago
The memory stat is not done in real time, it have some gap with
real value. In CPU-less NUMA node, the values of MemTotal and
MemFree can be nearly equal, the gap may cause MemFree bigger
than MemTotal, it leads MemUsed is negative which print as a large
positive number.

cat /sys/devices/system/node/node17/meminfo
Node 17 MemTotal:        4194304 kB
Node 17 MemFree:         4195552 kB
Node 17 MemUsed:        18446744073709550368 kB
Node 17 Active:               52 kB
Node 17 Inactive:            320 kB
Node 17 Active(anon):          0 kB
Node 17 Inactive(anon):        0 kB
Node 17 Active(file):         52 kB
Node 17 Inactive(file):      320 kB
Node 17 Unevictable:           0 kB
Node 17 Mlocked:               0 kB
Node 17 Dirty:                 0 kB
Node 17 Writeback:             0 kB
Node 17 FilePages:           372 kB
Node 17 Mapped:              320 kB
Node 17 AnonPages:             0 kB
Node 17 Shmem:                 0 kB
Node 17 KernelStack:           0 kB
Node 17 PageTables:            0 kB
Node 17 NFS_Unstable:          0 kB
Node 17 Bounce:                0 kB
Node 17 WritebackTmp:          0 kB
Node 17 KReclaimable:          0 kB
Node 17 Slab:                  0 kB
Node 17 SReclaimable:          0 kB
Node 17 SUnreclaim:            0 kB
Node 17 AnonHugePages:     79872 kB
Node 17 ShmemHugePages:        0 kB
Node 17 ShmemPmdMapped:        0 kB
Node 17 FileHugePages:        0 kB
Node 17 FilePmdMapped:        0 kB
Node 17 HugePages_Total:     0
Node 17 HugePages_Free:      0
Node 17 HugePages_Surp:      0

To avoid this exception by refreshing vm_stat, when MemFree
is bigger than MemTotal.

Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
---
 include/linux/vmstat.h |  1 +
 mm/show_mem.c          | 10 ++++++++++
 mm/vmstat.c            | 15 ++++++++++-----
 3 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index 3c9c266cf782..6a7d2f3757b0 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -259,6 +259,7 @@ extern unsigned long node_page_state(struct pglist_data *pgdat,
 						enum node_stat_item item);
 extern unsigned long node_page_state_pages(struct pglist_data *pgdat,
 					   enum node_stat_item item);
+extern int refresh_node_page_state(void);
 extern void fold_vm_numa_events(void);
 #else
 #define sum_zone_node_page_state(node, item) global_zone_page_state(item)
diff --git a/mm/show_mem.c b/mm/show_mem.c
index 43aca5a2ac99..dc8d2b6056d3 100644
--- a/mm/show_mem.c
+++ b/mm/show_mem.c
@@ -106,6 +106,16 @@ void si_meminfo_node(struct sysinfo *val, int nid)
 	val->totalram = managed_pages;
 	val->sharedram = node_page_state(pgdat, NR_SHMEM);
 	val->freeram = sum_zone_node_page_state(nid, NR_FREE_PAGES);
+	if (val->freeram > val->totalram) {
+		int err = refresh_node_page_state();
+		if (err)
+			val->freeram = val->totalram;
+		else
+			val->freeram = sum_zone_node_page_state(nid, NR_FREE_PAGES);
+
+		if (val->freeram > val->totalram)
+			val->freeram = val->totalram;
+	}
 	val->totalhigh = managed_highpages;
 	val->freehigh = free_highpages;
 	val->mem_unit = PAGE_SIZE;
diff --git a/mm/vmstat.c b/mm/vmstat.c
index f534972f517d..96a2e03ec83e 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -881,6 +881,11 @@ static bool refresh_cpu_vm_stats(bool do_pagesets)
 	return changed;
 }
 
+static void refresh_vm_stats(struct work_struct *work)
+{
+	refresh_cpu_vm_stats(true);
+}
+
 /*
  * Fold the data for an offline cpu into the global array.
  * There cannot be any access by the offline cpu and therefore
@@ -1024,6 +1029,11 @@ unsigned long node_page_state(struct pglist_data *pgdat,
 
 	return node_page_state_pages(pgdat, item);
 }
+
+int refresh_node_page_state(void)
+{
+	return schedule_on_each_cpu(refresh_vm_stats);
+}
 #endif
 
 /*
@@ -1970,11 +1980,6 @@ static int sysctl_stat_interval __read_mostly = HZ;
 static int vmstat_late_init_done;
 
 #ifdef CONFIG_PROC_FS
-static void refresh_vm_stats(struct work_struct *work)
-{
-	refresh_cpu_vm_stats(true);
-}
-
 static int vmstat_refresh(const struct ctl_table *table, int write,
 		   void *buffer, size_t *lenp, loff_t *ppos)
 {
-- 
2.25.1
Re: [PATCH -next] mm: make sure freeram is smaller than totalram
Posted by David Hildenbrand (Arm) 2 months ago
On 4/13/26 13:57, Yang Yingliang wrote:
> The memory stat is not done in real time, it have some gap with
> real value. In CPU-less NUMA node, the values of MemTotal and
> MemFree can be nearly equal, the gap may cause MemFree bigger
> than MemTotal, it leads MemUsed is negative which print as a large
> positive number.

How does this interact with CPU-less NUMA node? Some concurrent memory
hotunplug, or how could be possible get MemFree that is larger than
MemTotal?

> 
> cat /sys/devices/system/node/node17/meminfo
> Node 17 MemTotal:        4194304 kB
> Node 17 MemFree:         4195552 kB
> Node 17 MemUsed:        18446744073709550368 kB
> Node 17 Active:               52 kB
> Node 17 Inactive:            320 kB
> Node 17 Active(anon):          0 kB
> Node 17 Inactive(anon):        0 kB
> Node 17 Active(file):         52 kB
> Node 17 Inactive(file):      320 kB
> Node 17 Unevictable:           0 kB
> Node 17 Mlocked:               0 kB
> Node 17 Dirty:                 0 kB
> Node 17 Writeback:             0 kB
> Node 17 FilePages:           372 kB
> Node 17 Mapped:              320 kB
> Node 17 AnonPages:             0 kB
> Node 17 Shmem:                 0 kB
> Node 17 KernelStack:           0 kB
> Node 17 PageTables:            0 kB
> Node 17 NFS_Unstable:          0 kB
> Node 17 Bounce:                0 kB
> Node 17 WritebackTmp:          0 kB
> Node 17 KReclaimable:          0 kB
> Node 17 Slab:                  0 kB
> Node 17 SReclaimable:          0 kB
> Node 17 SUnreclaim:            0 kB
> Node 17 AnonHugePages:     79872 kB
> Node 17 ShmemHugePages:        0 kB
> Node 17 ShmemPmdMapped:        0 kB
> Node 17 FileHugePages:        0 kB
> Node 17 FilePmdMapped:        0 kB
> Node 17 HugePages_Total:     0
> Node 17 HugePages_Free:      0
> Node 17 HugePages_Surp:      0
> 
> To avoid this exception by refreshing vm_stat, when MemFree
> is bigger than MemTotal.
> 

-- 
Cheers,

David
Re: [PATCH -next] mm: make sure freeram is smaller than totalram
Posted by kernel test robot 2 months ago
Hi Yang,

kernel test robot noticed the following build warnings:

[auto build test WARNING on akpm-mm/mm-everything]

url:    https://github.com/intel-lab-lkp/linux/commits/Yang-Yingliang/mm-make-sure-freeram-is-smaller-than-totalram/20260415-122059
base:   https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link:    https://lore.kernel.org/r/20260413115736.1237680-1-yangyingliang%40huawei.com
patch subject: [PATCH -next] mm: make sure freeram is smaller than totalram
config: arm64-randconfig-001-20260415 (https://download.01.org/0day-ci/archive/20260415/202604151917.t6ckjppJ-lkp@intel.com/config)
compiler: aarch64-linux-gcc (GCC) 15.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260415/202604151917.t6ckjppJ-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202604151917.t6ckjppJ-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> mm/vmstat.c:884:13: warning: 'refresh_vm_stats' defined but not used [-Wunused-function]
     884 | static void refresh_vm_stats(struct work_struct *work)
         |             ^~~~~~~~~~~~~~~~


vim +/refresh_vm_stats +884 mm/vmstat.c

   883	
 > 884	static void refresh_vm_stats(struct work_struct *work)
   885	{
   886		refresh_cpu_vm_stats(true);
   887	}
   888	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki