Kyle McMartin 2545857
From 82e3d4969144377d13da97d511e849e8cf3e6dcc Mon Sep 17 00:00:00 2001
Kyle McMartin 2545857
From: Mel Gorman <mel@csn.ul.ie>
Kyle McMartin 2545857
Date: Wed, 24 Nov 2010 22:24:24 -0500
Kyle McMartin 2545857
Subject: [PATCH 2/2] mm: vmstat: Use a single setter function and callback for adjusting percpu thresholds
Kyle McMartin 2545857
Kyle McMartin 2545857
reduce_pgdat_percpu_threshold() and restore_pgdat_percpu_threshold() exist
Kyle McMartin 2545857
to adjust the per-cpu vmstat thresholds while kswapd is awake to avoid
Kyle McMartin 2545857
errors due to counter drift.  The functions duplicate some code so this
Kyle McMartin 2545857
patch replaces them with a single set_pgdat_percpu_threshold() that takes
Kyle McMartin 2545857
a callback function to calculate the desired threshold as a parameter.
Kyle McMartin 2545857
Kyle McMartin 2545857
Signed-off-by: Mel Gorman <mel@csn.ul.ie>
Kyle McMartin 2545857
Reviewed-by: Christoph Lameter <cl@linux.com>
Kyle McMartin 2545857
Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Kyle McMartin 2545857
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Kyle McMartin 2545857
[the various mmotm patches updating this were rolled up. --kyle]
Kyle McMartin 2545857
[[http://userweb.kernel.org/~akpm/mmotm/broken-out/mm-vmstat-use-a-single-setter-function-and-callback-for-adjusting-percpu-thresholds-fix-set_pgdat_percpu_threshold-dont-use-for_each_online_cpu.patch]]
Kyle McMartin 2545857
---
Kyle McMartin 2545857
 include/linux/vmstat.h |   10 ++++++----
Kyle McMartin 2545857
 mm/vmscan.c            |   19 +++++++++++++++++--
Kyle McMartin 2545857
 mm/vmstat.c            |   36 +++++++-----------------------------
Kyle McMartin 2545857
 3 files changed, 30 insertions(+), 35 deletions(-)
Kyle McMartin 2545857
Kyle McMartin 2545857
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
Kyle McMartin 2545857
index e4cc21c..833e676 100644
Kyle McMartin 2545857
--- a/include/linux/vmstat.h
Kyle McMartin 2545857
+++ b/include/linux/vmstat.h
Kyle McMartin 2545857
@@ -254,8 +254,11 @@ extern void dec_zone_state(struct zone *, enum zone_stat_item);
Kyle McMartin 2545857
 extern void __dec_zone_state(struct zone *, enum zone_stat_item);
Kyle McMartin 2545857
 
Kyle McMartin 2545857
 void refresh_cpu_vm_stats(int);
Kyle McMartin 2545857
-void reduce_pgdat_percpu_threshold(pg_data_t *pgdat);
Kyle McMartin 2545857
-void restore_pgdat_percpu_threshold(pg_data_t *pgdat);
Kyle McMartin 2545857
+
Kyle McMartin 2545857
+int calculate_pressure_threshold(struct zone *zone);
Kyle McMartin 2545857
+int calculate_normal_threshold(struct zone *zone);
Kyle McMartin 2545857
+void set_pgdat_percpu_threshold(pg_data_t *pgdat,
Kyle McMartin 2545857
+				int (*calculate_pressure)(struct zone *));
Kyle McMartin 2545857
 #else /* CONFIG_SMP */
Kyle McMartin 2545857
 
Kyle McMartin 2545857
 /*
Kyle McMartin 2545857
@@ -300,8 +303,7 @@ static inline void __dec_zone_page_state(struct page *page,
Kyle McMartin 2545857
 #define dec_zone_page_state __dec_zone_page_state
Kyle McMartin 2545857
 #define mod_zone_page_state __mod_zone_page_state
Kyle McMartin 2545857
 
Kyle McMartin 2545857
-static inline void reduce_pgdat_percpu_threshold(pg_data_t *pgdat) { }
Kyle McMartin 2545857
-static inline void restore_pgdat_percpu_threshold(pg_data_t *pgdat) { }
Kyle McMartin 2545857
+#define set_pgdat_percpu_threshold(pgdat, callback) { }
Kyle McMartin 2545857
 
Kyle McMartin 2545857
 static inline void refresh_cpu_vm_stats(int cpu) { }
Kyle McMartin 2545857
 #endif
Kyle McMartin 2545857
diff --git a/mm/vmscan.c b/mm/vmscan.c
Kyle McMartin 2545857
index 3e71cb1..ba39948 100644
Kyle McMartin 2545857
--- a/mm/vmscan.c
Kyle McMartin 2545857
+++ b/mm/vmscan.c
Kyle McMartin 2545857
@@ -2378,9 +2378,24 @@ static int kswapd(void *p)
Kyle McMartin 2545857
 				 */
Kyle McMartin 2545857
 				if (!sleeping_prematurely(pgdat, order, remaining)) {
Kyle McMartin 2545857
 					trace_mm_vmscan_kswapd_sleep(pgdat->node_id);
Kyle McMartin 2545857
-					restore_pgdat_percpu_threshold(pgdat);
Kyle McMartin 2545857
+
Kyle McMartin 2545857
+					/*
Kyle McMartin 2545857
+					 * vmstat counters are not perfectly
Kyle McMartin 2545857
+					 * accurate and the estimated value
Kyle McMartin 2545857
+					 * for counters such as NR_FREE_PAGES
Kyle McMartin 2545857
+					 * can deviate from the true value by
Kyle McMartin 2545857
+					 * nr_online_cpus * threshold. To
Kyle McMartin 2545857
+					 * avoid the zone watermarks being
Kyle McMartin 2545857
+					 * breached while under pressure, we
Kyle McMartin 2545857
+					 * reduce the per-cpu vmstat threshold
Kyle McMartin 2545857
+					 * while kswapd is awake and restore
Kyle McMartin 2545857
+					 * them before going back to sleep.
Kyle McMartin 2545857
+					 */
Kyle McMartin 2545857
+					set_pgdat_percpu_threshold(pgdat,
Kyle McMartin 2545857
+						calculate_normal_threshold);
Kyle McMartin 2545857
 					schedule();
Kyle McMartin 2545857
-					reduce_pgdat_percpu_threshold(pgdat);
Kyle McMartin 2545857
+					set_pgdat_percpu_threshold(pgdat,
Kyle McMartin 2545857
+						calculate_pressure_threshold);
Kyle McMartin 2545857
 				} else {
Kyle McMartin 2545857
 					if (remaining)
Kyle McMartin 2545857
 						count_vm_event(KSWAPD_LOW_WMARK_HIT_QUICKLY);
Kyle McMartin 2545857
diff --git a/mm/vmstat.c b/mm/vmstat.c
Kyle McMartin 2545857
index 4d7faeb..511c2c0 100644
Kyle McMartin 2545857
--- a/mm/vmstat.c
Kyle McMartin 2545857
+++ b/mm/vmstat.c
Kyle McMartin 2545857
@@ -81,7 +81,7 @@ EXPORT_SYMBOL(vm_stat);
Kyle McMartin 2545857
 
Kyle McMartin 2545857
 #ifdef CONFIG_SMP
Kyle McMartin 2545857
 
Kyle McMartin 2545857
-static int calculate_pressure_threshold(struct zone *zone)
Kyle McMartin 2545857
+int calculate_pressure_threshold(struct zone *zone)
Kyle McMartin 2545857
 {
Kyle McMartin 2545857
 	int threshold;
Kyle McMartin 2545857
 	int watermark_distance;
Kyle McMartin 2545857
@@ -105,7 +105,7 @@ static int calculate_pressure_threshold(struct zone *zone)
Kyle McMartin 2545857
 	return threshold;
Kyle McMartin 2545857
 }
Kyle McMartin 2545857
 
Kyle McMartin 2545857
-static int calculate_threshold(struct zone *zone)
Kyle McMartin 2545857
+int calculate_normal_threshold(struct zone *zone)
Kyle McMartin 2545857
 {
Kyle McMartin 2545857
 	int threshold;
Kyle McMartin 2545857
 	int mem;	/* memory in 128 MB units */
Kyle McMartin 2545857
@@ -164,7 +164,7 @@ static void refresh_zone_stat_thresholds(void)
Kyle McMartin 2545857
 	for_each_populated_zone(zone) {
Kyle McMartin 2545857
 		unsigned long max_drift, tolerate_drift;
Kyle McMartin 2545857
 
Kyle McMartin 2545857
-		threshold = calculate_threshold(zone);
Kyle McMartin 2545857
+		threshold = calculate_normal_threshold(zone);
Kyle McMartin 2545857
 
Kyle McMartin 2545857
 		for_each_online_cpu(cpu)
Kyle McMartin 2545857
 			per_cpu_ptr(zone->pageset, cpu)->stat_threshold
Kyle McMartin 2545857
@@ -183,46 +183,24 @@ static void refresh_zone_stat_thresholds(void)
Kyle McMartin 2545857
 	}
Kyle McMartin 2545857
 }
Kyle McMartin 2545857
 
Kyle McMartin 2545857
-void reduce_pgdat_percpu_threshold(pg_data_t *pgdat)
Kyle McMartin 2545857
+void set_pgdat_percpu_threshold(pg_data_t *pgdat,
Kyle McMartin 2545857
+				int (*calculate_pressure)(struct zone *))
Kyle McMartin 2545857
 {
Kyle McMartin 2545857
 	struct zone *zone;
Kyle McMartin 2545857
 	int cpu;
Kyle McMartin 2545857
 	int threshold;
Kyle McMartin 2545857
 	int i;
Kyle McMartin 2545857
 
Kyle McMartin 2545857
-	get_online_cpus();
Kyle McMartin 2545857
-	for (i = 0; i < pgdat->nr_zones; i++) {
Kyle McMartin 2545857
-		zone = &pgdat->node_zones[i];
Kyle McMartin 2545857
-		if (!zone->percpu_drift_mark)
Kyle McMartin 2545857
-			continue;
Kyle McMartin 2545857
-
Kyle McMartin 2545857
-		threshold = calculate_pressure_threshold(zone);
Kyle McMartin 2545857
-		for_each_online_cpu(cpu)
Kyle McMartin 2545857
-			per_cpu_ptr(zone->pageset, cpu)->stat_threshold
Kyle McMartin 2545857
-							= threshold;
Kyle McMartin 2545857
-	}
Kyle McMartin 2545857
-	put_online_cpus();
Kyle McMartin 2545857
-}
Kyle McMartin 2545857
-
Kyle McMartin 2545857
-void restore_pgdat_percpu_threshold(pg_data_t *pgdat)
Kyle McMartin 2545857
-{
Kyle McMartin 2545857
-	struct zone *zone;
Kyle McMartin 2545857
-	int cpu;
Kyle McMartin 2545857
-	int threshold;
Kyle McMartin 2545857
-	int i;
Kyle McMartin 2545857
-
Kyle McMartin 2545857
-	get_online_cpus();
Kyle McMartin 2545857
 	for (i = 0; i < pgdat->nr_zones; i++) {
Kyle McMartin 2545857
 		zone = &pgdat->node_zones[i];
Kyle McMartin 2545857
 		if (!zone->percpu_drift_mark)
Kyle McMartin 2545857
 			continue;
Kyle McMartin 2545857
 
Kyle McMartin 2545857
-		threshold = calculate_threshold(zone);
Kyle McMartin 2545857
-		for_each_online_cpu(cpu)
Kyle McMartin 2545857
+		threshold = (*calculate_pressure)(zone);
Kyle McMartin 2545857
+		for_each_possible_cpu(cpu)
Kyle McMartin 2545857
 			per_cpu_ptr(zone->pageset, cpu)->stat_threshold
Kyle McMartin 2545857
 							= threshold;
Kyle McMartin 2545857
 	}
Kyle McMartin 2545857
-	put_online_cpus();
Kyle McMartin 2545857
 }
Kyle McMartin 2545857
 
Kyle McMartin 2545857
 /*
Kyle McMartin 2545857
-- 
Kyle McMartin 2545857
1.7.3.2
Kyle McMartin 2545857