diff options
author | Shaohua Li <shaohua.li@intel.com> | 2011-08-25 18:59:12 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-08-25 19:25:34 -0400 |
commit | 439423f6894aa0dec22187526827456f5004baed (patch) | |
tree | 1f22238a24b83e0beb1467a1f73b0db952c69894 /mm/vmscan.c | |
parent | 4c30c6f566c0989ddaee3407da44751e340a63ed (diff) |
vmscan: clear ZONE_CONGESTED for zone with good watermark
ZONE_CONGESTED is only cleared in kswapd, but pages can be freed in any
task. It's possible ZONE_CONGESTED isn't cleared in some cases:
1. the zone is already balanced just entering balance_pgdat() for
order-0 because concurrent tasks free memory. In this case, later
check will skip the zone as it's balanced so the flag isn't cleared.
2. high order balance fallbacks to order-0. quote from Mel: At the
end of balance_pgdat(), kswapd uses the following logic;
If reclaiming at high order {
for each zone {
if all_unreclaimable
skip
if watermark is not met
order = 0
loop again
/* watermark is met */
clear congested
}
}
i.e. it clears ZONE_CONGESTED if it the zone is balanced. if not,
it restarts balancing at order-0. However, if the higher zones are
balanced for order-0, kswapd will miss clearing ZONE_CONGESTED as
that only happens after a zone is shrunk. This can mean that
wait_iff_congested() stalls unnecessarily.
This patch makes kswapd clear ZONE_CONGESTED during its initial
highmem->dma scan for zones that are already balanced.
Signed-off-by: Shaohua Li <shaohua.li@intel.com>
Acked-by: Mel Gorman <mgorman@suse.de>
Reviewed-by: Minchan Kim <minchan.kim@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/vmscan.c')
-rw-r--r-- | mm/vmscan.c | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c index 22631e0994b3..b7719ec10dc5 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -2529,6 +2529,9 @@ loop_again: | |||
2529 | high_wmark_pages(zone), 0, 0)) { | 2529 | high_wmark_pages(zone), 0, 0)) { |
2530 | end_zone = i; | 2530 | end_zone = i; |
2531 | break; | 2531 | break; |
2532 | } else { | ||
2533 | /* If balanced, clear the congested flag */ | ||
2534 | zone_clear_flag(zone, ZONE_CONGESTED); | ||
2532 | } | 2535 | } |
2533 | } | 2536 | } |
2534 | if (i < 0) | 2537 | if (i < 0) |