diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/page_alloc.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 6fb46c1589b9..2c38a30d064e 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -57,6 +57,7 @@ | |||
57 | #include <linux/ftrace_event.h> | 57 | #include <linux/ftrace_event.h> |
58 | #include <linux/memcontrol.h> | 58 | #include <linux/memcontrol.h> |
59 | #include <linux/prefetch.h> | 59 | #include <linux/prefetch.h> |
60 | #include <linux/migrate.h> | ||
60 | #include <linux/page-debug-flags.h> | 61 | #include <linux/page-debug-flags.h> |
61 | 62 | ||
62 | #include <asm/tlbflush.h> | 63 | #include <asm/tlbflush.h> |
@@ -5550,6 +5551,193 @@ out: | |||
5550 | spin_unlock_irqrestore(&zone->lock, flags); | 5551 | spin_unlock_irqrestore(&zone->lock, flags); |
5551 | } | 5552 | } |
5552 | 5553 | ||
5554 | #ifdef CONFIG_CMA | ||
5555 | |||
5556 | static unsigned long pfn_max_align_down(unsigned long pfn) | ||
5557 | { | ||
5558 | return pfn & ~(max_t(unsigned long, MAX_ORDER_NR_PAGES, | ||
5559 | pageblock_nr_pages) - 1); | ||
5560 | } | ||
5561 | |||
5562 | static unsigned long pfn_max_align_up(unsigned long pfn) | ||
5563 | { | ||
5564 | return ALIGN(pfn, max_t(unsigned long, MAX_ORDER_NR_PAGES, | ||
5565 | pageblock_nr_pages)); | ||
5566 | } | ||
5567 | |||
5568 | static struct page * | ||
5569 | __alloc_contig_migrate_alloc(struct page *page, unsigned long private, | ||
5570 | int **resultp) | ||
5571 | { | ||
5572 | return alloc_page(GFP_HIGHUSER_MOVABLE); | ||
5573 | } | ||
5574 | |||
5575 | /* [start, end) must belong to a single zone. */ | ||
5576 | static int __alloc_contig_migrate_range(unsigned long start, unsigned long end) | ||
5577 | { | ||
5578 | /* This function is based on compact_zone() from compaction.c. */ | ||
5579 | |||
5580 | unsigned long pfn = start; | ||
5581 | unsigned int tries = 0; | ||
5582 | int ret = 0; | ||
5583 | |||
5584 | struct compact_control cc = { | ||
5585 | .nr_migratepages = 0, | ||
5586 | .order = -1, | ||
5587 | .zone = page_zone(pfn_to_page(start)), | ||
5588 | .sync = true, | ||
5589 | }; | ||
5590 | INIT_LIST_HEAD(&cc.migratepages); | ||
5591 | |||
5592 | migrate_prep_local(); | ||
5593 | |||
5594 | while (pfn < end || !list_empty(&cc.migratepages)) { | ||
5595 | if (fatal_signal_pending(current)) { | ||
5596 | ret = -EINTR; | ||
5597 | break; | ||
5598 | } | ||
5599 | |||
5600 | if (list_empty(&cc.migratepages)) { | ||
5601 | cc.nr_migratepages = 0; | ||
5602 | pfn = isolate_migratepages_range(cc.zone, &cc, | ||
5603 | pfn, end); | ||
5604 | if (!pfn) { | ||
5605 | ret = -EINTR; | ||
5606 | break; | ||
5607 | } | ||
5608 | tries = 0; | ||
5609 | } else if (++tries == 5) { | ||
5610 | ret = ret < 0 ? ret : -EBUSY; | ||
5611 | break; | ||
5612 | } | ||
5613 | |||
5614 | ret = migrate_pages(&cc.migratepages, | ||
5615 | __alloc_contig_migrate_alloc, | ||
5616 | 0, false, true); | ||
5617 | } | ||
5618 | |||
5619 | putback_lru_pages(&cc.migratepages); | ||
5620 | return ret > 0 ? 0 : ret; | ||
5621 | } | ||
5622 | |||
5623 | /** | ||
5624 | * alloc_contig_range() -- tries to allocate given range of pages | ||
5625 | * @start: start PFN to allocate | ||
5626 | * @end: one-past-the-last PFN to allocate | ||
5627 | * | ||
5628 | * The PFN range does not have to be pageblock or MAX_ORDER_NR_PAGES | ||
5629 | * aligned, however it's the caller's responsibility to guarantee that | ||
5630 | * we are the only thread that changes migrate type of pageblocks the | ||
5631 | * pages fall in. | ||
5632 | * | ||
5633 | * The PFN range must belong to a single zone. | ||
5634 | * | ||
5635 | * Returns zero on success or negative error code. On success all | ||
5636 | * pages which PFN is in [start, end) are allocated for the caller and | ||
5637 | * need to be freed with free_contig_range(). | ||
5638 | */ | ||
5639 | int alloc_contig_range(unsigned long start, unsigned long end) | ||
5640 | { | ||
5641 | struct zone *zone = page_zone(pfn_to_page(start)); | ||
5642 | unsigned long outer_start, outer_end; | ||
5643 | int ret = 0, order; | ||
5644 | |||
5645 | /* | ||
5646 | * What we do here is we mark all pageblocks in range as | ||
5647 | * MIGRATE_ISOLATE. Because pageblock and max order pages may | ||
5648 | * have different sizes, and due to the way page allocator | ||
5649 | * work, we align the range to biggest of the two pages so | ||
5650 | * that page allocator won't try to merge buddies from | ||
5651 | * different pageblocks and change MIGRATE_ISOLATE to some | ||
5652 | * other migration type. | ||
5653 | * | ||
5654 | * Once the pageblocks are marked as MIGRATE_ISOLATE, we | ||
5655 | * migrate the pages from an unaligned range (ie. pages that | ||
5656 | * we are interested in). This will put all the pages in | ||
5657 | * range back to page allocator as MIGRATE_ISOLATE. | ||
5658 | * | ||
5659 | * When this is done, we take the pages in range from page | ||
5660 | * allocator removing them from the buddy system. This way | ||
5661 | * page allocator will never consider using them. | ||
5662 | * | ||
5663 | * This lets us mark the pageblocks back as | ||
5664 | * MIGRATE_CMA/MIGRATE_MOVABLE so that free pages in the | ||
5665 | * aligned range but not in the unaligned, original range are | ||
5666 | * put back to page allocator so that buddy can use them. | ||
5667 | */ | ||
5668 | |||
5669 | ret = start_isolate_page_range(pfn_max_align_down(start), | ||
5670 | pfn_max_align_up(end)); | ||
5671 | if (ret) | ||
5672 | goto done; | ||
5673 | |||
5674 | ret = __alloc_contig_migrate_range(start, end); | ||
5675 | if (ret) | ||
5676 | goto done; | ||
5677 | |||
5678 | /* | ||
5679 | * Pages from [start, end) are within a MAX_ORDER_NR_PAGES | ||
5680 | * aligned blocks that are marked as MIGRATE_ISOLATE. What's | ||
5681 | * more, all pages in [start, end) are free in page allocator. | ||
5682 | * What we are going to do is to allocate all pages from | ||
5683 | * [start, end) (that is remove them from page allocator). | ||
5684 | * | ||
5685 | * The only problem is that pages at the beginning and at the | ||
5686 | * end of interesting range may be not aligned with pages that | ||
5687 | * page allocator holds, ie. they can be part of higher order | ||
5688 | * pages. Because of this, we reserve the bigger range and | ||
5689 | * once this is done free the pages we are not interested in. | ||
5690 | * | ||
5691 | * We don't have to hold zone->lock here because the pages are | ||
5692 | * isolated thus they won't get removed from buddy. | ||
5693 | */ | ||
5694 | |||
5695 | lru_add_drain_all(); | ||
5696 | drain_all_pages(); | ||
5697 | |||
5698 | order = 0; | ||
5699 | outer_start = start; | ||
5700 | while (!PageBuddy(pfn_to_page(outer_start))) { | ||
5701 | if (++order >= MAX_ORDER) { | ||
5702 | ret = -EBUSY; | ||
5703 | goto done; | ||
5704 | } | ||
5705 | outer_start &= ~0UL << order; | ||
5706 | } | ||
5707 | |||
5708 | /* Make sure the range is really isolated. */ | ||
5709 | if (test_pages_isolated(outer_start, end)) { | ||
5710 | pr_warn("alloc_contig_range test_pages_isolated(%lx, %lx) failed\n", | ||
5711 | outer_start, end); | ||
5712 | ret = -EBUSY; | ||
5713 | goto done; | ||
5714 | } | ||
5715 | |||
5716 | outer_end = isolate_freepages_range(outer_start, end); | ||
5717 | if (!outer_end) { | ||
5718 | ret = -EBUSY; | ||
5719 | goto done; | ||
5720 | } | ||
5721 | |||
5722 | /* Free head and tail (if any) */ | ||
5723 | if (start != outer_start) | ||
5724 | free_contig_range(outer_start, start - outer_start); | ||
5725 | if (end != outer_end) | ||
5726 | free_contig_range(end, outer_end - end); | ||
5727 | |||
5728 | done: | ||
5729 | undo_isolate_page_range(pfn_max_align_down(start), | ||
5730 | pfn_max_align_up(end)); | ||
5731 | return ret; | ||
5732 | } | ||
5733 | |||
5734 | void free_contig_range(unsigned long pfn, unsigned nr_pages) | ||
5735 | { | ||
5736 | for (; nr_pages--; ++pfn) | ||
5737 | __free_page(pfn_to_page(pfn)); | ||
5738 | } | ||
5739 | #endif | ||
5740 | |||
5553 | #ifdef CONFIG_MEMORY_HOTREMOVE | 5741 | #ifdef CONFIG_MEMORY_HOTREMOVE |
5554 | /* | 5742 | /* |
5555 | * All pages in the range must be isolated before calling this. | 5743 | * All pages in the range must be isolated before calling this. |