aboutsummaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r--mm/page_alloc.c188
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
5556static 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
5562static 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
5568static 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. */
5576static 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 */
5639int 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
5728done:
5729 undo_isolate_page_range(pfn_max_align_down(start),
5730 pfn_max_align_up(end));
5731 return ret;
5732}
5733
5734void 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.