diff options
| -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; |
