diff options
author | Mel Gorman <mgorman@suse.de> | 2013-07-03 18:01:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-03 19:07:28 -0400 |
commit | 2ab44f434586b8ccb11f781b4c2730492e6628f5 (patch) | |
tree | 5ff85d452c1fe1b34e04e3238c2de36e39203bcf /mm/vmscan.c | |
parent | b8e83b942a16eb73e63406592d3178207a4f07a1 (diff) |
mm: vmscan: decide whether to compact the pgdat based on reclaim progress
In the past, kswapd makes a decision on whether to compact memory after
the pgdat was considered balanced. This more or less worked but it is
late to make such a decision and does not fit well now that kswapd makes
a decision whether to exit the zone scanning loop depending on reclaim
progress.
This patch will compact a pgdat if at least the requested number of
pages were reclaimed from unbalanced zones for a given priority. If any
zone is currently balanced, kswapd will not call compaction as it is
expected the necessary pages are already available.
Signed-off-by: Mel Gorman <mgorman@suse.de>
Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Reviewed-by: Michal Hocko <mhocko@suse.cz>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
Tested-by: Zlatko Calusic <zcalusic@bitsync.net>
Cc: dormando <dormando@rydia.net>
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 | 59 |
1 files changed, 30 insertions, 29 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c index 1c10ee512215..cd0980393bac 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -2661,7 +2661,8 @@ static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, long remaining, | |||
2661 | */ | 2661 | */ |
2662 | static bool kswapd_shrink_zone(struct zone *zone, | 2662 | static bool kswapd_shrink_zone(struct zone *zone, |
2663 | struct scan_control *sc, | 2663 | struct scan_control *sc, |
2664 | unsigned long lru_pages) | 2664 | unsigned long lru_pages, |
2665 | unsigned long *nr_attempted) | ||
2665 | { | 2666 | { |
2666 | unsigned long nr_slab; | 2667 | unsigned long nr_slab; |
2667 | struct reclaim_state *reclaim_state = current->reclaim_state; | 2668 | struct reclaim_state *reclaim_state = current->reclaim_state; |
@@ -2677,6 +2678,9 @@ static bool kswapd_shrink_zone(struct zone *zone, | |||
2677 | nr_slab = shrink_slab(&shrink, sc->nr_scanned, lru_pages); | 2678 | nr_slab = shrink_slab(&shrink, sc->nr_scanned, lru_pages); |
2678 | sc->nr_reclaimed += reclaim_state->reclaimed_slab; | 2679 | sc->nr_reclaimed += reclaim_state->reclaimed_slab; |
2679 | 2680 | ||
2681 | /* Account for the number of pages attempted to reclaim */ | ||
2682 | *nr_attempted += sc->nr_to_reclaim; | ||
2683 | |||
2680 | if (nr_slab == 0 && !zone_reclaimable(zone)) | 2684 | if (nr_slab == 0 && !zone_reclaimable(zone)) |
2681 | zone->all_unreclaimable = 1; | 2685 | zone->all_unreclaimable = 1; |
2682 | 2686 | ||
@@ -2724,7 +2728,9 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order, | |||
2724 | 2728 | ||
2725 | do { | 2729 | do { |
2726 | unsigned long lru_pages = 0; | 2730 | unsigned long lru_pages = 0; |
2731 | unsigned long nr_attempted = 0; | ||
2727 | bool raise_priority = true; | 2732 | bool raise_priority = true; |
2733 | bool pgdat_needs_compaction = (order > 0); | ||
2728 | 2734 | ||
2729 | sc.nr_reclaimed = 0; | 2735 | sc.nr_reclaimed = 0; |
2730 | 2736 | ||
@@ -2774,7 +2780,21 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order, | |||
2774 | for (i = 0; i <= end_zone; i++) { | 2780 | for (i = 0; i <= end_zone; i++) { |
2775 | struct zone *zone = pgdat->node_zones + i; | 2781 | struct zone *zone = pgdat->node_zones + i; |
2776 | 2782 | ||
2783 | if (!populated_zone(zone)) | ||
2784 | continue; | ||
2785 | |||
2777 | lru_pages += zone_reclaimable_pages(zone); | 2786 | lru_pages += zone_reclaimable_pages(zone); |
2787 | |||
2788 | /* | ||
2789 | * If any zone is currently balanced then kswapd will | ||
2790 | * not call compaction as it is expected that the | ||
2791 | * necessary pages are already available. | ||
2792 | */ | ||
2793 | if (pgdat_needs_compaction && | ||
2794 | zone_watermark_ok(zone, order, | ||
2795 | low_wmark_pages(zone), | ||
2796 | *classzone_idx, 0)) | ||
2797 | pgdat_needs_compaction = false; | ||
2778 | } | 2798 | } |
2779 | 2799 | ||
2780 | /* | 2800 | /* |
@@ -2843,7 +2863,8 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order, | |||
2843 | * already being scanned that high | 2863 | * already being scanned that high |
2844 | * watermark would be met at 100% efficiency. | 2864 | * watermark would be met at 100% efficiency. |
2845 | */ | 2865 | */ |
2846 | if (kswapd_shrink_zone(zone, &sc, lru_pages)) | 2866 | if (kswapd_shrink_zone(zone, &sc, lru_pages, |
2867 | &nr_attempted)) | ||
2847 | raise_priority = false; | 2868 | raise_priority = false; |
2848 | } | 2869 | } |
2849 | 2870 | ||
@@ -2896,6 +2917,13 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order, | |||
2896 | break; | 2917 | break; |
2897 | 2918 | ||
2898 | /* | 2919 | /* |
2920 | * Compact if necessary and kswapd is reclaiming at least the | ||
2921 | * high watermark number of pages as requsted | ||
2922 | */ | ||
2923 | if (pgdat_needs_compaction && sc.nr_reclaimed > nr_attempted) | ||
2924 | compact_pgdat(pgdat, order); | ||
2925 | |||
2926 | /* | ||
2899 | * Raise priority if scanning rate is too low or there was no | 2927 | * Raise priority if scanning rate is too low or there was no |
2900 | * progress in reclaiming pages | 2928 | * progress in reclaiming pages |
2901 | */ | 2929 | */ |
@@ -2904,33 +2932,6 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order, | |||
2904 | } while (sc.priority >= 0 && | 2932 | } while (sc.priority >= 0 && |
2905 | !pgdat_balanced(pgdat, order, *classzone_idx)); | 2933 | !pgdat_balanced(pgdat, order, *classzone_idx)); |
2906 | 2934 | ||
2907 | /* | ||
2908 | * If kswapd was reclaiming at a higher order, it has the option of | ||
2909 | * sleeping without all zones being balanced. Before it does, it must | ||
2910 | * ensure that the watermarks for order-0 on *all* zones are met and | ||
2911 | * that the congestion flags are cleared. The congestion flag must | ||
2912 | * be cleared as kswapd is the only mechanism that clears the flag | ||
2913 | * and it is potentially going to sleep here. | ||
2914 | */ | ||
2915 | if (order) { | ||
2916 | int zones_need_compaction = 1; | ||
2917 | |||
2918 | for (i = 0; i <= end_zone; i++) { | ||
2919 | struct zone *zone = pgdat->node_zones + i; | ||
2920 | |||
2921 | if (!populated_zone(zone)) | ||
2922 | continue; | ||
2923 | |||
2924 | /* Check if the memory needs to be defragmented. */ | ||
2925 | if (zone_watermark_ok(zone, order, | ||
2926 | low_wmark_pages(zone), *classzone_idx, 0)) | ||
2927 | zones_need_compaction = 0; | ||
2928 | } | ||
2929 | |||
2930 | if (zones_need_compaction) | ||
2931 | compact_pgdat(pgdat, order); | ||
2932 | } | ||
2933 | |||
2934 | out: | 2935 | out: |
2935 | /* | 2936 | /* |
2936 | * Return the order we were reclaiming at so prepare_kswapd_sleep() | 2937 | * Return the order we were reclaiming at so prepare_kswapd_sleep() |