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.c58
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/* 2614static 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 */
2618void 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
2626static 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
2661out: 2664/*
2665 * Free a 0-order page
2666 * cold == true ? free a cold page : free a hot page
2667 */
2668void 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:
2668void free_hot_cold_page_list(struct list_head *list, bool cold) 2684void 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/*