summaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorJoonsoo Kim <iamjoonsoo.kim@lge.com>2016-03-15 17:57:48 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-03-15 19:55:16 -0400
commite1409c325fdc1fef7b3d8025c51892355f065d15 (patch)
tree43486b8130eba24ee7380e0ccddf49551fd0b420 /mm
parent623446e4dc45b37740268165107cc63abb3022f0 (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.c41
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
555isolate_freepages_range(struct compact_control *cc, 555isolate_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
864isolate_migratepages_range(struct compact_control *cc, unsigned long start_pfn, 870isolate_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;
1104static isolate_migrate_t isolate_migratepages(struct zone *zone, 1115static 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);