diff options
Diffstat (limited to 'mm/compaction.c')
-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 | ||