diff options
| -rw-r--r-- | mm/compaction.c | 75 |
1 files changed, 54 insertions, 21 deletions
diff --git a/mm/compaction.c b/mm/compaction.c index 74a8c825ff28..ee20fc044b91 100644 --- a/mm/compaction.c +++ b/mm/compaction.c | |||
| @@ -250,31 +250,34 @@ typedef enum { | |||
| 250 | ISOLATE_SUCCESS, /* Pages isolated, migrate */ | 250 | ISOLATE_SUCCESS, /* Pages isolated, migrate */ |
| 251 | } isolate_migrate_t; | 251 | } isolate_migrate_t; |
| 252 | 252 | ||
| 253 | /* | 253 | /** |
| 254 | * Isolate all pages that can be migrated from the block pointed to by | 254 | * isolate_migratepages_range() - isolate all migrate-able pages in range. |
| 255 | * the migrate scanner within compact_control. | 255 | * @zone: Zone pages are in. |
| 256 | * @cc: Compaction control structure. | ||
| 257 | * @low_pfn: The first PFN of the range. | ||
| 258 | * @end_pfn: The one-past-the-last PFN of the range. | ||
| 259 | * | ||
| 260 | * Isolate all pages that can be migrated from the range specified by | ||
| 261 | * [low_pfn, end_pfn). Returns zero if there is a fatal signal | ||
| 262 | * pending), otherwise PFN of the first page that was not scanned | ||
| 263 | * (which may be both less, equal to or more then end_pfn). | ||
| 264 | * | ||
| 265 | * Assumes that cc->migratepages is empty and cc->nr_migratepages is | ||
| 266 | * zero. | ||
| 267 | * | ||
| 268 | * Apart from cc->migratepages and cc->nr_migratetypes this function | ||
| 269 | * does not modify any cc's fields, in particular it does not modify | ||
| 270 | * (or read for that matter) cc->migrate_pfn. | ||
| 256 | */ | 271 | */ |
| 257 | static isolate_migrate_t isolate_migratepages(struct zone *zone, | 272 | static unsigned long |
| 258 | struct compact_control *cc) | 273 | isolate_migratepages_range(struct zone *zone, struct compact_control *cc, |
| 274 | unsigned long low_pfn, unsigned long end_pfn) | ||
| 259 | { | 275 | { |
| 260 | unsigned long low_pfn, end_pfn; | ||
| 261 | unsigned long last_pageblock_nr = 0, pageblock_nr; | 276 | unsigned long last_pageblock_nr = 0, pageblock_nr; |
| 262 | unsigned long nr_scanned = 0, nr_isolated = 0; | 277 | unsigned long nr_scanned = 0, nr_isolated = 0; |
| 263 | struct list_head *migratelist = &cc->migratepages; | 278 | struct list_head *migratelist = &cc->migratepages; |
| 264 | isolate_mode_t mode = ISOLATE_ACTIVE|ISOLATE_INACTIVE; | 279 | isolate_mode_t mode = ISOLATE_ACTIVE|ISOLATE_INACTIVE; |
| 265 | 280 | ||
| 266 | /* Do not scan outside zone boundaries */ | ||
| 267 | low_pfn = max(cc->migrate_pfn, zone->zone_start_pfn); | ||
| 268 | |||
| 269 | /* Only scan within a pageblock boundary */ | ||
| 270 | end_pfn = ALIGN(low_pfn + pageblock_nr_pages, pageblock_nr_pages); | ||
| 271 | |||
| 272 | /* Do not cross the free scanner or scan within a memory hole */ | ||
| 273 | if (end_pfn > cc->free_pfn || !pfn_valid(low_pfn)) { | ||
| 274 | cc->migrate_pfn = end_pfn; | ||
| 275 | return ISOLATE_NONE; | ||
| 276 | } | ||
| 277 | |||
| 278 | /* | 281 | /* |
| 279 | * Ensure that there are not too many pages isolated from the LRU | 282 | * Ensure that there are not too many pages isolated from the LRU |
| 280 | * list by either parallel reclaimers or compaction. If there are, | 283 | * list by either parallel reclaimers or compaction. If there are, |
| @@ -283,12 +286,12 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone, | |||
| 283 | while (unlikely(too_many_isolated(zone))) { | 286 | while (unlikely(too_many_isolated(zone))) { |
| 284 | /* async migration should just abort */ | 287 | /* async migration should just abort */ |
| 285 | if (!cc->sync) | 288 | if (!cc->sync) |
| 286 | return ISOLATE_ABORT; | 289 | return 0; |
| 287 | 290 | ||
| 288 | congestion_wait(BLK_RW_ASYNC, HZ/10); | 291 | congestion_wait(BLK_RW_ASYNC, HZ/10); |
| 289 | 292 | ||
| 290 | if (fatal_signal_pending(current)) | 293 | if (fatal_signal_pending(current)) |
| 291 | return ISOLATE_ABORT; | 294 | return 0; |
| 292 | } | 295 | } |
| 293 | 296 | ||
| 294 | /* Time to isolate some pages for migration */ | 297 | /* Time to isolate some pages for migration */ |
| @@ -396,10 +399,40 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone, | |||
| 396 | acct_isolated(zone, cc); | 399 | acct_isolated(zone, cc); |
| 397 | 400 | ||
| 398 | spin_unlock_irq(&zone->lru_lock); | 401 | spin_unlock_irq(&zone->lru_lock); |
| 399 | cc->migrate_pfn = low_pfn; | ||
| 400 | 402 | ||
| 401 | trace_mm_compaction_isolate_migratepages(nr_scanned, nr_isolated); | 403 | trace_mm_compaction_isolate_migratepages(nr_scanned, nr_isolated); |
| 402 | 404 | ||
| 405 | return low_pfn; | ||
| 406 | } | ||
| 407 | |||
| 408 | /* | ||
| 409 | * Isolate all pages that can be migrated from the block pointed to by | ||
| 410 | * the migrate scanner within compact_control. | ||
| 411 | */ | ||
| 412 | static isolate_migrate_t isolate_migratepages(struct zone *zone, | ||
| 413 | struct compact_control *cc) | ||
| 414 | { | ||
| 415 | unsigned long low_pfn, end_pfn; | ||
| 416 | |||
| 417 | /* Do not scan outside zone boundaries */ | ||
| 418 | low_pfn = max(cc->migrate_pfn, zone->zone_start_pfn); | ||
| 419 | |||
| 420 | /* Only scan within a pageblock boundary */ | ||
| 421 | end_pfn = ALIGN(low_pfn + pageblock_nr_pages, pageblock_nr_pages); | ||
| 422 | |||
| 423 | /* Do not cross the free scanner or scan within a memory hole */ | ||
| 424 | if (end_pfn > cc->free_pfn || !pfn_valid(low_pfn)) { | ||
| 425 | cc->migrate_pfn = end_pfn; | ||
| 426 | return ISOLATE_NONE; | ||
| 427 | } | ||
| 428 | |||
| 429 | /* Perform the isolation */ | ||
| 430 | low_pfn = isolate_migratepages_range(zone, cc, low_pfn, end_pfn); | ||
| 431 | if (!low_pfn) | ||
| 432 | return ISOLATE_ABORT; | ||
| 433 | |||
| 434 | cc->migrate_pfn = low_pfn; | ||
| 435 | |||
| 403 | return ISOLATE_SUCCESS; | 436 | return ISOLATE_SUCCESS; |
| 404 | } | 437 | } |
| 405 | 438 | ||
