diff options
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r-- | mm/page_alloc.c | 87 |
1 files changed, 66 insertions, 21 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 099790052bfe..6a683f819439 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -5297,12 +5297,65 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags, | |||
5297 | * page allocater never alloc memory from ISOLATE block. | 5297 | * page allocater never alloc memory from ISOLATE block. |
5298 | */ | 5298 | */ |
5299 | 5299 | ||
5300 | static int | ||
5301 | __count_immobile_pages(struct zone *zone, struct page *page, int count) | ||
5302 | { | ||
5303 | unsigned long pfn, iter, found; | ||
5304 | /* | ||
5305 | * For avoiding noise data, lru_add_drain_all() should be called | ||
5306 | * If ZONE_MOVABLE, the zone never contains immobile pages | ||
5307 | */ | ||
5308 | if (zone_idx(zone) == ZONE_MOVABLE) | ||
5309 | return true; | ||
5310 | |||
5311 | if (get_pageblock_migratetype(page) == MIGRATE_MOVABLE) | ||
5312 | return true; | ||
5313 | |||
5314 | pfn = page_to_pfn(page); | ||
5315 | for (found = 0, iter = 0; iter < pageblock_nr_pages; iter++) { | ||
5316 | unsigned long check = pfn + iter; | ||
5317 | |||
5318 | if (!pfn_valid_within(check)) { | ||
5319 | iter++; | ||
5320 | continue; | ||
5321 | } | ||
5322 | page = pfn_to_page(check); | ||
5323 | if (!page_count(page)) { | ||
5324 | if (PageBuddy(page)) | ||
5325 | iter += (1 << page_order(page)) - 1; | ||
5326 | continue; | ||
5327 | } | ||
5328 | if (!PageLRU(page)) | ||
5329 | found++; | ||
5330 | /* | ||
5331 | * If there are RECLAIMABLE pages, we need to check it. | ||
5332 | * But now, memory offline itself doesn't call shrink_slab() | ||
5333 | * and it still to be fixed. | ||
5334 | */ | ||
5335 | /* | ||
5336 | * If the page is not RAM, page_count()should be 0. | ||
5337 | * we don't need more check. This is an _used_ not-movable page. | ||
5338 | * | ||
5339 | * The problematic thing here is PG_reserved pages. PG_reserved | ||
5340 | * is set to both of a memory hole page and a _used_ kernel | ||
5341 | * page at boot. | ||
5342 | */ | ||
5343 | if (found > count) | ||
5344 | return false; | ||
5345 | } | ||
5346 | return true; | ||
5347 | } | ||
5348 | |||
5349 | bool is_pageblock_removable_nolock(struct page *page) | ||
5350 | { | ||
5351 | struct zone *zone = page_zone(page); | ||
5352 | return __count_immobile_pages(zone, page, 0); | ||
5353 | } | ||
5354 | |||
5300 | int set_migratetype_isolate(struct page *page) | 5355 | int set_migratetype_isolate(struct page *page) |
5301 | { | 5356 | { |
5302 | struct zone *zone; | 5357 | struct zone *zone; |
5303 | struct page *curr_page; | 5358 | unsigned long flags, pfn; |
5304 | unsigned long flags, pfn, iter; | ||
5305 | unsigned long immobile = 0; | ||
5306 | struct memory_isolate_notify arg; | 5359 | struct memory_isolate_notify arg; |
5307 | int notifier_ret; | 5360 | int notifier_ret; |
5308 | int ret = -EBUSY; | 5361 | int ret = -EBUSY; |
@@ -5312,11 +5365,6 @@ int set_migratetype_isolate(struct page *page) | |||
5312 | zone_idx = zone_idx(zone); | 5365 | zone_idx = zone_idx(zone); |
5313 | 5366 | ||
5314 | spin_lock_irqsave(&zone->lock, flags); | 5367 | spin_lock_irqsave(&zone->lock, flags); |
5315 | if (get_pageblock_migratetype(page) == MIGRATE_MOVABLE || | ||
5316 | zone_idx == ZONE_MOVABLE) { | ||
5317 | ret = 0; | ||
5318 | goto out; | ||
5319 | } | ||
5320 | 5368 | ||
5321 | pfn = page_to_pfn(page); | 5369 | pfn = page_to_pfn(page); |
5322 | arg.start_pfn = pfn; | 5370 | arg.start_pfn = pfn; |
@@ -5338,21 +5386,18 @@ int set_migratetype_isolate(struct page *page) | |||
5338 | notifier_ret = notifier_to_errno(notifier_ret); | 5386 | notifier_ret = notifier_to_errno(notifier_ret); |
5339 | if (notifier_ret) | 5387 | if (notifier_ret) |
5340 | goto out; | 5388 | goto out; |
5341 | 5389 | /* | |
5342 | for (iter = pfn; iter < (pfn + pageblock_nr_pages); iter++) { | 5390 | * FIXME: Now, memory hotplug doesn't call shrink_slab() by itself. |
5343 | if (!pfn_valid_within(pfn)) | 5391 | * We just check MOVABLE pages. |
5344 | continue; | 5392 | */ |
5345 | 5393 | if (__count_immobile_pages(zone, page, arg.pages_found)) | |
5346 | curr_page = pfn_to_page(iter); | ||
5347 | if (!page_count(curr_page) || PageLRU(curr_page)) | ||
5348 | continue; | ||
5349 | |||
5350 | immobile++; | ||
5351 | } | ||
5352 | |||
5353 | if (arg.pages_found == immobile) | ||
5354 | ret = 0; | 5394 | ret = 0; |
5355 | 5395 | ||
5396 | /* | ||
5397 | * immobile means "not-on-lru" paes. If immobile is larger than | ||
5398 | * removable-by-driver pages reported by notifier, we'll fail. | ||
5399 | */ | ||
5400 | |||
5356 | out: | 5401 | out: |
5357 | if (!ret) { | 5402 | if (!ret) { |
5358 | set_pageblock_migratetype(page, MIGRATE_ISOLATE); | 5403 | set_pageblock_migratetype(page, MIGRATE_ISOLATE); |