diff options
author | Joonsoo Kim <iamjoonsoo.kim@lge.com> | 2016-03-15 17:57:48 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-15 19:55:16 -0400 |
commit | e1409c325fdc1fef7b3d8025c51892355f065d15 (patch) | |
tree | 43486b8130eba24ee7380e0ccddf49551fd0b420 /mm | |
parent | 623446e4dc45b37740268165107cc63abb3022f0 (diff) |
mm/compaction: pass only pageblock aligned range to pageblock_pfn_to_page
pageblock_pfn_to_page() is used to check there is valid pfn and all
pages in the pageblock is in a single zone. If there is a hole in the
pageblock, passing arbitrary position to pageblock_pfn_to_page() could
cause to skip whole pageblock scanning, instead of just skipping the
hole page. For deterministic behaviour, it's better to always pass
pageblock aligned range to pageblock_pfn_to_page(). It will also help
further optimization on pageblock_pfn_to_page() in the following patch.
Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Aaron Lu <aaron.lu@intel.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Rik van Riel <riel@redhat.com>
Acked-by: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/compaction.c | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/mm/compaction.c b/mm/compaction.c index 56fa3216a6b4..8ce36ebc8d15 100644 --- a/mm/compaction.c +++ b/mm/compaction.c | |||
@@ -555,13 +555,17 @@ unsigned long | |||
555 | isolate_freepages_range(struct compact_control *cc, | 555 | isolate_freepages_range(struct compact_control *cc, |
556 | unsigned long start_pfn, unsigned long end_pfn) | 556 | unsigned long start_pfn, unsigned long end_pfn) |
557 | { | 557 | { |
558 | unsigned long isolated, pfn, block_end_pfn; | 558 | unsigned long isolated, pfn, block_start_pfn, block_end_pfn; |
559 | LIST_HEAD(freelist); | 559 | LIST_HEAD(freelist); |
560 | 560 | ||
561 | pfn = start_pfn; | 561 | pfn = start_pfn; |
562 | block_start_pfn = pfn & ~(pageblock_nr_pages - 1); | ||
563 | if (block_start_pfn < cc->zone->zone_start_pfn) | ||
564 | block_start_pfn = cc->zone->zone_start_pfn; | ||
562 | block_end_pfn = ALIGN(pfn + 1, pageblock_nr_pages); | 565 | block_end_pfn = ALIGN(pfn + 1, pageblock_nr_pages); |
563 | 566 | ||
564 | for (; pfn < end_pfn; pfn += isolated, | 567 | for (; pfn < end_pfn; pfn += isolated, |
568 | block_start_pfn = block_end_pfn, | ||
565 | block_end_pfn += pageblock_nr_pages) { | 569 | block_end_pfn += pageblock_nr_pages) { |
566 | /* Protect pfn from changing by isolate_freepages_block */ | 570 | /* Protect pfn from changing by isolate_freepages_block */ |
567 | unsigned long isolate_start_pfn = pfn; | 571 | unsigned long isolate_start_pfn = pfn; |
@@ -574,11 +578,13 @@ isolate_freepages_range(struct compact_control *cc, | |||
574 | * scanning range to right one. | 578 | * scanning range to right one. |
575 | */ | 579 | */ |
576 | if (pfn >= block_end_pfn) { | 580 | if (pfn >= block_end_pfn) { |
581 | block_start_pfn = pfn & ~(pageblock_nr_pages - 1); | ||
577 | block_end_pfn = ALIGN(pfn + 1, pageblock_nr_pages); | 582 | block_end_pfn = ALIGN(pfn + 1, pageblock_nr_pages); |
578 | block_end_pfn = min(block_end_pfn, end_pfn); | 583 | block_end_pfn = min(block_end_pfn, end_pfn); |
579 | } | 584 | } |
580 | 585 | ||
581 | if (!pageblock_pfn_to_page(pfn, block_end_pfn, cc->zone)) | 586 | if (!pageblock_pfn_to_page(block_start_pfn, |
587 | block_end_pfn, cc->zone)) | ||
582 | break; | 588 | break; |
583 | 589 | ||
584 | isolated = isolate_freepages_block(cc, &isolate_start_pfn, | 590 | isolated = isolate_freepages_block(cc, &isolate_start_pfn, |
@@ -864,18 +870,23 @@ unsigned long | |||
864 | isolate_migratepages_range(struct compact_control *cc, unsigned long start_pfn, | 870 | isolate_migratepages_range(struct compact_control *cc, unsigned long start_pfn, |
865 | unsigned long end_pfn) | 871 | unsigned long end_pfn) |
866 | { | 872 | { |
867 | unsigned long pfn, block_end_pfn; | 873 | unsigned long pfn, block_start_pfn, block_end_pfn; |
868 | 874 | ||
869 | /* Scan block by block. First and last block may be incomplete */ | 875 | /* Scan block by block. First and last block may be incomplete */ |
870 | pfn = start_pfn; | 876 | pfn = start_pfn; |
877 | block_start_pfn = pfn & ~(pageblock_nr_pages - 1); | ||
878 | if (block_start_pfn < cc->zone->zone_start_pfn) | ||
879 | block_start_pfn = cc->zone->zone_start_pfn; | ||
871 | block_end_pfn = ALIGN(pfn + 1, pageblock_nr_pages); | 880 | block_end_pfn = ALIGN(pfn + 1, pageblock_nr_pages); |
872 | 881 | ||
873 | for (; pfn < end_pfn; pfn = block_end_pfn, | 882 | for (; pfn < end_pfn; pfn = block_end_pfn, |
883 | block_start_pfn = block_end_pfn, | ||
874 | block_end_pfn += pageblock_nr_pages) { | 884 | block_end_pfn += pageblock_nr_pages) { |
875 | 885 | ||
876 | block_end_pfn = min(block_end_pfn, end_pfn); | 886 | block_end_pfn = min(block_end_pfn, end_pfn); |
877 | 887 | ||
878 | if (!pageblock_pfn_to_page(pfn, block_end_pfn, cc->zone)) | 888 | if (!pageblock_pfn_to_page(block_start_pfn, |
889 | block_end_pfn, cc->zone)) | ||
879 | continue; | 890 | continue; |
880 | 891 | ||
881 | pfn = isolate_migratepages_block(cc, pfn, block_end_pfn, | 892 | pfn = isolate_migratepages_block(cc, pfn, block_end_pfn, |
@@ -1104,7 +1115,9 @@ int sysctl_compact_unevictable_allowed __read_mostly = 1; | |||
1104 | static isolate_migrate_t isolate_migratepages(struct zone *zone, | 1115 | static isolate_migrate_t isolate_migratepages(struct zone *zone, |
1105 | struct compact_control *cc) | 1116 | struct compact_control *cc) |
1106 | { | 1117 | { |
1107 | unsigned long low_pfn, end_pfn; | 1118 | unsigned long block_start_pfn; |
1119 | unsigned long block_end_pfn; | ||
1120 | unsigned long low_pfn; | ||
1108 | unsigned long isolate_start_pfn; | 1121 | unsigned long isolate_start_pfn; |
1109 | struct page *page; | 1122 | struct page *page; |
1110 | const isolate_mode_t isolate_mode = | 1123 | const isolate_mode_t isolate_mode = |
@@ -1116,16 +1129,21 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone, | |||
1116 | * initialized by compact_zone() | 1129 | * initialized by compact_zone() |
1117 | */ | 1130 | */ |
1118 | low_pfn = cc->migrate_pfn; | 1131 | low_pfn = cc->migrate_pfn; |
1132 | block_start_pfn = cc->migrate_pfn & ~(pageblock_nr_pages - 1); | ||
1133 | if (block_start_pfn < zone->zone_start_pfn) | ||
1134 | block_start_pfn = zone->zone_start_pfn; | ||
1119 | 1135 | ||
1120 | /* Only scan within a pageblock boundary */ | 1136 | /* Only scan within a pageblock boundary */ |
1121 | end_pfn = ALIGN(low_pfn + 1, pageblock_nr_pages); | 1137 | block_end_pfn = ALIGN(low_pfn + 1, pageblock_nr_pages); |
1122 | 1138 | ||
1123 | /* | 1139 | /* |
1124 | * Iterate over whole pageblocks until we find the first suitable. | 1140 | * Iterate over whole pageblocks until we find the first suitable. |
1125 | * Do not cross the free scanner. | 1141 | * Do not cross the free scanner. |
1126 | */ | 1142 | */ |
1127 | for (; end_pfn <= cc->free_pfn; | 1143 | for (; block_end_pfn <= cc->free_pfn; |
1128 | low_pfn = end_pfn, end_pfn += pageblock_nr_pages) { | 1144 | low_pfn = block_end_pfn, |
1145 | block_start_pfn = block_end_pfn, | ||
1146 | block_end_pfn += pageblock_nr_pages) { | ||
1129 | 1147 | ||
1130 | /* | 1148 | /* |
1131 | * This can potentially iterate a massively long zone with | 1149 | * This can potentially iterate a massively long zone with |
@@ -1136,7 +1154,8 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone, | |||
1136 | && compact_should_abort(cc)) | 1154 | && compact_should_abort(cc)) |
1137 | break; | 1155 | break; |
1138 | 1156 | ||
1139 | page = pageblock_pfn_to_page(low_pfn, end_pfn, zone); | 1157 | page = pageblock_pfn_to_page(block_start_pfn, block_end_pfn, |
1158 | zone); | ||
1140 | if (!page) | 1159 | if (!page) |
1141 | continue; | 1160 | continue; |
1142 | 1161 | ||
@@ -1155,8 +1174,8 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone, | |||
1155 | 1174 | ||
1156 | /* Perform the isolation */ | 1175 | /* Perform the isolation */ |
1157 | isolate_start_pfn = low_pfn; | 1176 | isolate_start_pfn = low_pfn; |
1158 | low_pfn = isolate_migratepages_block(cc, low_pfn, end_pfn, | 1177 | low_pfn = isolate_migratepages_block(cc, low_pfn, |
1159 | isolate_mode); | 1178 | block_end_pfn, isolate_mode); |
1160 | 1179 | ||
1161 | if (!low_pfn || cc->contended) { | 1180 | if (!low_pfn || cc->contended) { |
1162 | acct_isolated(zone, cc); | 1181 | acct_isolated(zone, cc); |