diff options
Diffstat (limited to 'mm/compaction.c')
-rw-r--r-- | mm/compaction.c | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/mm/compaction.c b/mm/compaction.c index f171a83707ce..b4930bf93c8a 100644 --- a/mm/compaction.c +++ b/mm/compaction.c | |||
@@ -242,6 +242,7 @@ __reset_isolation_pfn(struct zone *zone, unsigned long pfn, bool check_source, | |||
242 | bool check_target) | 242 | bool check_target) |
243 | { | 243 | { |
244 | struct page *page = pfn_to_online_page(pfn); | 244 | struct page *page = pfn_to_online_page(pfn); |
245 | struct page *block_page; | ||
245 | struct page *end_page; | 246 | struct page *end_page; |
246 | unsigned long block_pfn; | 247 | unsigned long block_pfn; |
247 | 248 | ||
@@ -267,20 +268,26 @@ __reset_isolation_pfn(struct zone *zone, unsigned long pfn, bool check_source, | |||
267 | get_pageblock_migratetype(page) != MIGRATE_MOVABLE) | 268 | get_pageblock_migratetype(page) != MIGRATE_MOVABLE) |
268 | return false; | 269 | return false; |
269 | 270 | ||
271 | /* Ensure the start of the pageblock or zone is online and valid */ | ||
272 | block_pfn = pageblock_start_pfn(pfn); | ||
273 | block_page = pfn_to_online_page(max(block_pfn, zone->zone_start_pfn)); | ||
274 | if (block_page) { | ||
275 | page = block_page; | ||
276 | pfn = block_pfn; | ||
277 | } | ||
278 | |||
279 | /* Ensure the end of the pageblock or zone is online and valid */ | ||
280 | block_pfn += pageblock_nr_pages; | ||
281 | block_pfn = min(block_pfn, zone_end_pfn(zone) - 1); | ||
282 | end_page = pfn_to_online_page(block_pfn); | ||
283 | if (!end_page) | ||
284 | return false; | ||
285 | |||
270 | /* | 286 | /* |
271 | * Only clear the hint if a sample indicates there is either a | 287 | * Only clear the hint if a sample indicates there is either a |
272 | * free page or an LRU page in the block. One or other condition | 288 | * free page or an LRU page in the block. One or other condition |
273 | * is necessary for the block to be a migration source/target. | 289 | * is necessary for the block to be a migration source/target. |
274 | */ | 290 | */ |
275 | block_pfn = pageblock_start_pfn(pfn); | ||
276 | pfn = max(block_pfn, zone->zone_start_pfn); | ||
277 | page = pfn_to_page(pfn); | ||
278 | if (zone != page_zone(page)) | ||
279 | return false; | ||
280 | pfn = block_pfn + pageblock_nr_pages; | ||
281 | pfn = min(pfn, zone_end_pfn(zone)); | ||
282 | end_page = pfn_to_page(pfn); | ||
283 | |||
284 | do { | 291 | do { |
285 | if (pfn_valid_within(pfn)) { | 292 | if (pfn_valid_within(pfn)) { |
286 | if (check_source && PageLRU(page)) { | 293 | if (check_source && PageLRU(page)) { |
@@ -309,7 +316,7 @@ __reset_isolation_pfn(struct zone *zone, unsigned long pfn, bool check_source, | |||
309 | static void __reset_isolation_suitable(struct zone *zone) | 316 | static void __reset_isolation_suitable(struct zone *zone) |
310 | { | 317 | { |
311 | unsigned long migrate_pfn = zone->zone_start_pfn; | 318 | unsigned long migrate_pfn = zone->zone_start_pfn; |
312 | unsigned long free_pfn = zone_end_pfn(zone); | 319 | unsigned long free_pfn = zone_end_pfn(zone) - 1; |
313 | unsigned long reset_migrate = free_pfn; | 320 | unsigned long reset_migrate = free_pfn; |
314 | unsigned long reset_free = migrate_pfn; | 321 | unsigned long reset_free = migrate_pfn; |
315 | bool source_set = false; | 322 | bool source_set = false; |