diff options
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r-- | mm/page_alloc.c | 58 |
1 files changed, 44 insertions, 14 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index ab648e359602..6a3c4a1d513f 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -2611,24 +2611,26 @@ void mark_free_pages(struct zone *zone) | |||
2611 | } | 2611 | } |
2612 | #endif /* CONFIG_PM */ | 2612 | #endif /* CONFIG_PM */ |
2613 | 2613 | ||
2614 | /* | 2614 | static bool free_hot_cold_page_prepare(struct page *page, unsigned long pfn) |
2615 | * Free a 0-order page | ||
2616 | * cold == true ? free a cold page : free a hot page | ||
2617 | */ | ||
2618 | void free_hot_cold_page(struct page *page, bool cold) | ||
2619 | { | 2615 | { |
2620 | struct zone *zone = page_zone(page); | ||
2621 | struct per_cpu_pages *pcp; | ||
2622 | unsigned long flags; | ||
2623 | unsigned long pfn = page_to_pfn(page); | ||
2624 | int migratetype; | 2616 | int migratetype; |
2625 | 2617 | ||
2626 | if (!free_pcp_prepare(page)) | 2618 | if (!free_pcp_prepare(page)) |
2627 | return; | 2619 | return false; |
2628 | 2620 | ||
2629 | migratetype = get_pfnblock_migratetype(page, pfn); | 2621 | migratetype = get_pfnblock_migratetype(page, pfn); |
2630 | set_pcppage_migratetype(page, migratetype); | 2622 | set_pcppage_migratetype(page, migratetype); |
2631 | local_irq_save(flags); | 2623 | return true; |
2624 | } | ||
2625 | |||
2626 | static void free_hot_cold_page_commit(struct page *page, unsigned long pfn, | ||
2627 | bool cold) | ||
2628 | { | ||
2629 | struct zone *zone = page_zone(page); | ||
2630 | struct per_cpu_pages *pcp; | ||
2631 | int migratetype; | ||
2632 | |||
2633 | migratetype = get_pcppage_migratetype(page); | ||
2632 | __count_vm_event(PGFREE); | 2634 | __count_vm_event(PGFREE); |
2633 | 2635 | ||
2634 | /* | 2636 | /* |
@@ -2641,7 +2643,7 @@ void free_hot_cold_page(struct page *page, bool cold) | |||
2641 | if (migratetype >= MIGRATE_PCPTYPES) { | 2643 | if (migratetype >= MIGRATE_PCPTYPES) { |
2642 | if (unlikely(is_migrate_isolate(migratetype))) { | 2644 | if (unlikely(is_migrate_isolate(migratetype))) { |
2643 | free_one_page(zone, page, pfn, 0, migratetype); | 2645 | free_one_page(zone, page, pfn, 0, migratetype); |
2644 | goto out; | 2646 | return; |
2645 | } | 2647 | } |
2646 | migratetype = MIGRATE_MOVABLE; | 2648 | migratetype = MIGRATE_MOVABLE; |
2647 | } | 2649 | } |
@@ -2657,8 +2659,22 @@ void free_hot_cold_page(struct page *page, bool cold) | |||
2657 | free_pcppages_bulk(zone, batch, pcp); | 2659 | free_pcppages_bulk(zone, batch, pcp); |
2658 | pcp->count -= batch; | 2660 | pcp->count -= batch; |
2659 | } | 2661 | } |
2662 | } | ||
2660 | 2663 | ||
2661 | out: | 2664 | /* |
2665 | * Free a 0-order page | ||
2666 | * cold == true ? free a cold page : free a hot page | ||
2667 | */ | ||
2668 | void free_hot_cold_page(struct page *page, bool cold) | ||
2669 | { | ||
2670 | unsigned long flags; | ||
2671 | unsigned long pfn = page_to_pfn(page); | ||
2672 | |||
2673 | if (!free_hot_cold_page_prepare(page, pfn)) | ||
2674 | return; | ||
2675 | |||
2676 | local_irq_save(flags); | ||
2677 | free_hot_cold_page_commit(page, pfn, cold); | ||
2662 | local_irq_restore(flags); | 2678 | local_irq_restore(flags); |
2663 | } | 2679 | } |
2664 | 2680 | ||
@@ -2668,11 +2684,25 @@ out: | |||
2668 | void free_hot_cold_page_list(struct list_head *list, bool cold) | 2684 | void free_hot_cold_page_list(struct list_head *list, bool cold) |
2669 | { | 2685 | { |
2670 | struct page *page, *next; | 2686 | struct page *page, *next; |
2687 | unsigned long flags, pfn; | ||
2688 | |||
2689 | /* Prepare pages for freeing */ | ||
2690 | list_for_each_entry_safe(page, next, list, lru) { | ||
2691 | pfn = page_to_pfn(page); | ||
2692 | if (!free_hot_cold_page_prepare(page, pfn)) | ||
2693 | list_del(&page->lru); | ||
2694 | set_page_private(page, pfn); | ||
2695 | } | ||
2671 | 2696 | ||
2697 | local_irq_save(flags); | ||
2672 | list_for_each_entry_safe(page, next, list, lru) { | 2698 | list_for_each_entry_safe(page, next, list, lru) { |
2699 | unsigned long pfn = page_private(page); | ||
2700 | |||
2701 | set_page_private(page, 0); | ||
2673 | trace_mm_page_free_batched(page, cold); | 2702 | trace_mm_page_free_batched(page, cold); |
2674 | free_hot_cold_page(page, cold); | 2703 | free_hot_cold_page_commit(page, pfn, cold); |
2675 | } | 2704 | } |
2705 | local_irq_restore(flags); | ||
2676 | } | 2706 | } |
2677 | 2707 | ||
2678 | /* | 2708 | /* |