[PATCH] mm/vmstat: avoid taking zone lock in /proc/buddyinfo reads

Imran Khan posted 1 patch 3 days, 17 hours ago
mm/vmstat.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
[PATCH] mm/vmstat: avoid taking zone lock in /proc/buddyinfo reads
Posted by Imran Khan 3 days, 17 hours ago
frag_show_print() just reads zone->free_area[order].nr_free, so
it can safely do this without needing the zone->lock.

Pass nolock=true from frag_show(), so that walk_zones_in_node()
can skip the zone->lock acquisition.

Signed-off-by: Imran Khan <imran.f.khan@oracle.com>
---
 mm/vmstat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mm/vmstat.c b/mm/vmstat.c
index f534972f517de..7b93fbf9af092 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -1568,7 +1568,7 @@ static void frag_show_print(struct seq_file *m, pg_data_t *pgdat,
 static int frag_show(struct seq_file *m, void *arg)
 {
 	pg_data_t *pgdat = (pg_data_t *)arg;
-	walk_zones_in_node(m, pgdat, true, false, frag_show_print);
+	walk_zones_in_node(m, pgdat, true, true, frag_show_print);
 	return 0;
 }
 

base-commit: e43ffb69e0438cddd72aaa30898b4dc446f664f8
-- 
2.34.1
Re: [PATCH] mm/vmstat: avoid taking zone lock in /proc/buddyinfo reads
Posted by Vlastimil Babka (SUSE) 2 days, 19 hours ago
On 6/4/26 15:42, Imran Khan wrote:
> frag_show_print() just reads zone->free_area[order].nr_free, so
> it can safely do this without needing the zone->lock.
> 
> Pass nolock=true from frag_show(), so that walk_zones_in_node()
> can skip the zone->lock acquisition.
> 
> Signed-off-by: Imran Khan <imran.f.khan@oracle.com>

Acked-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>


> ---
>  mm/vmstat.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/mm/vmstat.c b/mm/vmstat.c
> index f534972f517de..7b93fbf9af092 100644
> --- a/mm/vmstat.c
> +++ b/mm/vmstat.c
> @@ -1568,7 +1568,7 @@ static void frag_show_print(struct seq_file *m, pg_data_t *pgdat,
>  static int frag_show(struct seq_file *m, void *arg)
>  {
>  	pg_data_t *pgdat = (pg_data_t *)arg;
> -	walk_zones_in_node(m, pgdat, true, false, frag_show_print);
> +	walk_zones_in_node(m, pgdat, true, true, frag_show_print);
>  	return 0;
>  }
>  
> 
> base-commit: e43ffb69e0438cddd72aaa30898b4dc446f664f8
Re: [PATCH] mm/vmstat: avoid taking zone lock in /proc/buddyinfo reads
Posted by Joshua Hahn 3 days, 14 hours ago
On Thu,  4 Jun 2026 21:42:45 +0800 Imran Khan <imran.f.khan@oracle.com> wrote:

> frag_show_print() just reads zone->free_area[order].nr_free, so
> it can safely do this without needing the zone->lock.
> 
> Pass nolock=true from frag_show(), so that walk_zones_in_node()
> can skip the zone->lock acquisition.

Hello Imran, thank you for the patch!

Seems reasonable to me, and I think this sentiment was already explicitly
encoded in a comment block in frag_show_print:

		/*
		 * Access to nr_free is lockless as nr_free is used only for
		 * printing purposes. Use data_race to avoid KCSAN warning.
		 */
		seq_printf(m, "%6lu ", data_race(zone->free_area[order].nr_free));

Plus, we have a data_race() here so it seems like lockless reading was
always the intent anyways. So:

Reviewed-by: Joshua Hahn <joshua.hahnjy@gmail.com>

Digging into this a bit more, I did find something worth noting.

Commit af1c31acc85325 "mm/vmstat: annotate data race for
zone->free_area[order].nr_free" was the commit that added the
data_race() here, in response to a KCSAN report. But looking into it, I
don't think KCSAN was reporting a data race for this callsite, it was
actually reporting it for a different one in
extfrag_for_order->fill_contig_page_info. Maybe the author there added
the data_race() for frag_show_print just to be safe as well, even though
at the time it was protected by a zone->lock anyways.

Just something I thought was interesting to note. Thanks again!
Joshua

> Signed-off-by: Imran Khan <imran.f.khan@oracle.com>
> ---
>  mm/vmstat.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/mm/vmstat.c b/mm/vmstat.c
> index f534972f517de..7b93fbf9af092 100644
> --- a/mm/vmstat.c
> +++ b/mm/vmstat.c
> @@ -1568,7 +1568,7 @@ static void frag_show_print(struct seq_file *m, pg_data_t *pgdat,
>  static int frag_show(struct seq_file *m, void *arg)
>  {
>  	pg_data_t *pgdat = (pg_data_t *)arg;
> -	walk_zones_in_node(m, pgdat, true, false, frag_show_print);
> +	walk_zones_in_node(m, pgdat, true, true, frag_show_print);
>  	return 0;
>  }
>  
> 
> base-commit: e43ffb69e0438cddd72aaa30898b4dc446f664f8
> -- 
> 2.34.1