aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorAlex Shi2011-10-31 19:08:39 -0500
committerGreg Kroah-Hartman2012-08-01 14:27:17 -0500
commit5d62e5ca429b85ecadaa5042bdb1d8b88d4bfe80 (patch)
treea16a226a0b108d0f0a069c38d03e424ee3debc5f /mm
parenta7e32d7a2a801b7838b4159e9d73ea86f68ae002 (diff)
downloadkernel-common-5d62e5ca429b85ecadaa5042bdb1d8b88d4bfe80.tar.gz
kernel-common-5d62e5ca429b85ecadaa5042bdb1d8b88d4bfe80.tar.xz
kernel-common-5d62e5ca429b85ecadaa5042bdb1d8b88d4bfe80.zip
kswapd: avoid unnecessary rebalance after an unsuccessful balancing
commit d2ebd0f6b89567eb93ead4e2ca0cbe03021f344b upstream. Stable note: Fixes https://bugzilla.redhat.com/show_bug.cgi?id=712019. This patch reduces kswapd CPU usage. In commit 215ddd66 ("mm: vmscan: only read new_classzone_idx from pgdat when reclaiming successfully") , Mel Gorman said kswapd is better to sleep after a unsuccessful balancing if there is tighter reclaim request pending in the balancing. But in the following scenario, kswapd do something that is not matched our expectation. The patch fixes this issue. 1, Read pgdat request A (classzone_idx, order = 3) 2, balance_pgdat() 3, During pgdat, a new pgdat request B (classzone_idx, order = 5) is placed 4, balance_pgdat() returns but failed since returned order = 0 5, pgdat of request A assigned to balance_pgdat(), and do balancing again. While the expectation behavior of kswapd should try to sleep. Signed-off-by: Alex Shi <alex.shi@intel.com> Reviewed-by: Tim Chen <tim.c.chen@linux.intel.com> Acked-by: Mel Gorman <mgorman@suse.de> Tested-by: Pádraig Brady <P@draigBrady.com> Cc: Rik van Riel <riel@redhat.com> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Mel Gorman <mgorman@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/vmscan.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 45c40d66b74..5cc0f92eda3 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2844,7 +2844,9 @@ static void kswapd_try_to_sleep(pg_data_t *pgdat, int order, int classzone_idx)
2844static int kswapd(void *p) 2844static int kswapd(void *p)
2845{ 2845{
2846 unsigned long order, new_order; 2846 unsigned long order, new_order;
2847 unsigned balanced_order;
2847 int classzone_idx, new_classzone_idx; 2848 int classzone_idx, new_classzone_idx;
2849 int balanced_classzone_idx;
2848 pg_data_t *pgdat = (pg_data_t*)p; 2850 pg_data_t *pgdat = (pg_data_t*)p;
2849 struct task_struct *tsk = current; 2851 struct task_struct *tsk = current;
2850 2852
@@ -2875,7 +2877,9 @@ static int kswapd(void *p)
2875 set_freezable(); 2877 set_freezable();
2876 2878
2877 order = new_order = 0; 2879 order = new_order = 0;
2880 balanced_order = 0;
2878 classzone_idx = new_classzone_idx = pgdat->nr_zones - 1; 2881 classzone_idx = new_classzone_idx = pgdat->nr_zones - 1;
2882 balanced_classzone_idx = classzone_idx;
2879 for ( ; ; ) { 2883 for ( ; ; ) {
2880 int ret; 2884 int ret;
2881 2885
@@ -2884,7 +2888,8 @@ static int kswapd(void *p)
2884 * new request of a similar or harder type will succeed soon 2888 * new request of a similar or harder type will succeed soon
2885 * so consider going to sleep on the basis we reclaimed at 2889 * so consider going to sleep on the basis we reclaimed at
2886 */ 2890 */
2887 if (classzone_idx >= new_classzone_idx && order == new_order) { 2891 if (balanced_classzone_idx >= new_classzone_idx &&
2892 balanced_order == new_order) {
2888 new_order = pgdat->kswapd_max_order; 2893 new_order = pgdat->kswapd_max_order;
2889 new_classzone_idx = pgdat->classzone_idx; 2894 new_classzone_idx = pgdat->classzone_idx;
2890 pgdat->kswapd_max_order = 0; 2895 pgdat->kswapd_max_order = 0;
@@ -2899,7 +2904,8 @@ static int kswapd(void *p)
2899 order = new_order; 2904 order = new_order;
2900 classzone_idx = new_classzone_idx; 2905 classzone_idx = new_classzone_idx;
2901 } else { 2906 } else {
2902 kswapd_try_to_sleep(pgdat, order, classzone_idx); 2907 kswapd_try_to_sleep(pgdat, balanced_order,
2908 balanced_classzone_idx);
2903 order = pgdat->kswapd_max_order; 2909 order = pgdat->kswapd_max_order;
2904 classzone_idx = pgdat->classzone_idx; 2910 classzone_idx = pgdat->classzone_idx;
2905 pgdat->kswapd_max_order = 0; 2911 pgdat->kswapd_max_order = 0;
@@ -2916,7 +2922,9 @@ static int kswapd(void *p)
2916 */ 2922 */
2917 if (!ret) { 2923 if (!ret) {
2918 trace_mm_vmscan_kswapd_wake(pgdat->node_id, order); 2924 trace_mm_vmscan_kswapd_wake(pgdat->node_id, order);
2919 order = balance_pgdat(pgdat, order, &classzone_idx); 2925 balanced_classzone_idx = classzone_idx;
2926 balanced_order = balance_pgdat(pgdat, order,
2927 &balanced_classzone_idx);
2920 } 2928 }
2921 } 2929 }
2922 return 0; 2930 return 0;