diff options
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r-- | mm/page_alloc.c | 159 |
1 files changed, 81 insertions, 78 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index b2838c24e582..37576b822f06 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -537,7 +537,7 @@ static void __free_pages_ok(struct page *page, unsigned int order) | |||
537 | /* | 537 | /* |
538 | * permit the bootmem allocator to evade page validation on high-order frees | 538 | * permit the bootmem allocator to evade page validation on high-order frees |
539 | */ | 539 | */ |
540 | void fastcall __init __free_pages_bootmem(struct page *page, unsigned int order) | 540 | void __init __free_pages_bootmem(struct page *page, unsigned int order) |
541 | { | 541 | { |
542 | if (order == 0) { | 542 | if (order == 0) { |
543 | __ClearPageReserved(page); | 543 | __ClearPageReserved(page); |
@@ -890,31 +890,51 @@ void drain_zone_pages(struct zone *zone, struct per_cpu_pages *pcp) | |||
890 | } | 890 | } |
891 | #endif | 891 | #endif |
892 | 892 | ||
893 | static void __drain_pages(unsigned int cpu) | 893 | /* |
894 | * Drain pages of the indicated processor. | ||
895 | * | ||
896 | * The processor must either be the current processor and the | ||
897 | * thread pinned to the current processor or a processor that | ||
898 | * is not online. | ||
899 | */ | ||
900 | static void drain_pages(unsigned int cpu) | ||
894 | { | 901 | { |
895 | unsigned long flags; | 902 | unsigned long flags; |
896 | struct zone *zone; | 903 | struct zone *zone; |
897 | int i; | ||
898 | 904 | ||
899 | for_each_zone(zone) { | 905 | for_each_zone(zone) { |
900 | struct per_cpu_pageset *pset; | 906 | struct per_cpu_pageset *pset; |
907 | struct per_cpu_pages *pcp; | ||
901 | 908 | ||
902 | if (!populated_zone(zone)) | 909 | if (!populated_zone(zone)) |
903 | continue; | 910 | continue; |
904 | 911 | ||
905 | pset = zone_pcp(zone, cpu); | 912 | pset = zone_pcp(zone, cpu); |
906 | for (i = 0; i < ARRAY_SIZE(pset->pcp); i++) { | 913 | |
907 | struct per_cpu_pages *pcp; | 914 | pcp = &pset->pcp; |
908 | 915 | local_irq_save(flags); | |
909 | pcp = &pset->pcp[i]; | 916 | free_pages_bulk(zone, pcp->count, &pcp->list, 0); |
910 | local_irq_save(flags); | 917 | pcp->count = 0; |
911 | free_pages_bulk(zone, pcp->count, &pcp->list, 0); | 918 | local_irq_restore(flags); |
912 | pcp->count = 0; | ||
913 | local_irq_restore(flags); | ||
914 | } | ||
915 | } | 919 | } |
916 | } | 920 | } |
917 | 921 | ||
922 | /* | ||
923 | * Spill all of this CPU's per-cpu pages back into the buddy allocator. | ||
924 | */ | ||
925 | void drain_local_pages(void *arg) | ||
926 | { | ||
927 | drain_pages(smp_processor_id()); | ||
928 | } | ||
929 | |||
930 | /* | ||
931 | * Spill all the per-cpu pages from all CPUs back into the buddy allocator | ||
932 | */ | ||
933 | void drain_all_pages(void) | ||
934 | { | ||
935 | on_each_cpu(drain_local_pages, NULL, 0, 1); | ||
936 | } | ||
937 | |||
918 | #ifdef CONFIG_HIBERNATION | 938 | #ifdef CONFIG_HIBERNATION |
919 | 939 | ||
920 | void mark_free_pages(struct zone *zone) | 940 | void mark_free_pages(struct zone *zone) |
@@ -952,40 +972,9 @@ void mark_free_pages(struct zone *zone) | |||
952 | #endif /* CONFIG_PM */ | 972 | #endif /* CONFIG_PM */ |
953 | 973 | ||
954 | /* | 974 | /* |
955 | * Spill all of this CPU's per-cpu pages back into the buddy allocator. | ||
956 | */ | ||
957 | void drain_local_pages(void) | ||
958 | { | ||
959 | unsigned long flags; | ||
960 | |||
961 | local_irq_save(flags); | ||
962 | __drain_pages(smp_processor_id()); | ||
963 | local_irq_restore(flags); | ||
964 | } | ||
965 | |||
966 | void smp_drain_local_pages(void *arg) | ||
967 | { | ||
968 | drain_local_pages(); | ||
969 | } | ||
970 | |||
971 | /* | ||
972 | * Spill all the per-cpu pages from all CPUs back into the buddy allocator | ||
973 | */ | ||
974 | void drain_all_local_pages(void) | ||
975 | { | ||
976 | unsigned long flags; | ||
977 | |||
978 | local_irq_save(flags); | ||
979 | __drain_pages(smp_processor_id()); | ||
980 | local_irq_restore(flags); | ||
981 | |||
982 | smp_call_function(smp_drain_local_pages, NULL, 0, 1); | ||
983 | } | ||
984 | |||
985 | /* | ||
986 | * Free a 0-order page | 975 | * Free a 0-order page |
987 | */ | 976 | */ |
988 | static void fastcall free_hot_cold_page(struct page *page, int cold) | 977 | static void free_hot_cold_page(struct page *page, int cold) |
989 | { | 978 | { |
990 | struct zone *zone = page_zone(page); | 979 | struct zone *zone = page_zone(page); |
991 | struct per_cpu_pages *pcp; | 980 | struct per_cpu_pages *pcp; |
@@ -1001,10 +990,13 @@ static void fastcall free_hot_cold_page(struct page *page, int cold) | |||
1001 | arch_free_page(page, 0); | 990 | arch_free_page(page, 0); |
1002 | kernel_map_pages(page, 1, 0); | 991 | kernel_map_pages(page, 1, 0); |
1003 | 992 | ||
1004 | pcp = &zone_pcp(zone, get_cpu())->pcp[cold]; | 993 | pcp = &zone_pcp(zone, get_cpu())->pcp; |
1005 | local_irq_save(flags); | 994 | local_irq_save(flags); |
1006 | __count_vm_event(PGFREE); | 995 | __count_vm_event(PGFREE); |
1007 | list_add(&page->lru, &pcp->list); | 996 | if (cold) |
997 | list_add_tail(&page->lru, &pcp->list); | ||
998 | else | ||
999 | list_add(&page->lru, &pcp->list); | ||
1008 | set_page_private(page, get_pageblock_migratetype(page)); | 1000 | set_page_private(page, get_pageblock_migratetype(page)); |
1009 | pcp->count++; | 1001 | pcp->count++; |
1010 | if (pcp->count >= pcp->high) { | 1002 | if (pcp->count >= pcp->high) { |
@@ -1015,12 +1007,12 @@ static void fastcall free_hot_cold_page(struct page *page, int cold) | |||
1015 | put_cpu(); | 1007 | put_cpu(); |
1016 | } | 1008 | } |
1017 | 1009 | ||
1018 | void fastcall free_hot_page(struct page *page) | 1010 | void free_hot_page(struct page *page) |
1019 | { | 1011 | { |
1020 | free_hot_cold_page(page, 0); | 1012 | free_hot_cold_page(page, 0); |
1021 | } | 1013 | } |
1022 | 1014 | ||
1023 | void fastcall free_cold_page(struct page *page) | 1015 | void free_cold_page(struct page *page) |
1024 | { | 1016 | { |
1025 | free_hot_cold_page(page, 1); | 1017 | free_hot_cold_page(page, 1); |
1026 | } | 1018 | } |
@@ -1062,7 +1054,7 @@ again: | |||
1062 | if (likely(order == 0)) { | 1054 | if (likely(order == 0)) { |
1063 | struct per_cpu_pages *pcp; | 1055 | struct per_cpu_pages *pcp; |
1064 | 1056 | ||
1065 | pcp = &zone_pcp(zone, cpu)->pcp[cold]; | 1057 | pcp = &zone_pcp(zone, cpu)->pcp; |
1066 | local_irq_save(flags); | 1058 | local_irq_save(flags); |
1067 | if (!pcp->count) { | 1059 | if (!pcp->count) { |
1068 | pcp->count = rmqueue_bulk(zone, 0, | 1060 | pcp->count = rmqueue_bulk(zone, 0, |
@@ -1072,9 +1064,15 @@ again: | |||
1072 | } | 1064 | } |
1073 | 1065 | ||
1074 | /* Find a page of the appropriate migrate type */ | 1066 | /* Find a page of the appropriate migrate type */ |
1075 | list_for_each_entry(page, &pcp->list, lru) | 1067 | if (cold) { |
1076 | if (page_private(page) == migratetype) | 1068 | list_for_each_entry_reverse(page, &pcp->list, lru) |
1077 | break; | 1069 | if (page_private(page) == migratetype) |
1070 | break; | ||
1071 | } else { | ||
1072 | list_for_each_entry(page, &pcp->list, lru) | ||
1073 | if (page_private(page) == migratetype) | ||
1074 | break; | ||
1075 | } | ||
1078 | 1076 | ||
1079 | /* Allocate more to the pcp list if necessary */ | 1077 | /* Allocate more to the pcp list if necessary */ |
1080 | if (unlikely(&page->lru == &pcp->list)) { | 1078 | if (unlikely(&page->lru == &pcp->list)) { |
@@ -1569,7 +1567,7 @@ nofail_alloc: | |||
1569 | cond_resched(); | 1567 | cond_resched(); |
1570 | 1568 | ||
1571 | if (order != 0) | 1569 | if (order != 0) |
1572 | drain_all_local_pages(); | 1570 | drain_all_pages(); |
1573 | 1571 | ||
1574 | if (likely(did_some_progress)) { | 1572 | if (likely(did_some_progress)) { |
1575 | page = get_page_from_freelist(gfp_mask, order, | 1573 | page = get_page_from_freelist(gfp_mask, order, |
@@ -1643,7 +1641,7 @@ EXPORT_SYMBOL(__alloc_pages); | |||
1643 | /* | 1641 | /* |
1644 | * Common helper functions. | 1642 | * Common helper functions. |
1645 | */ | 1643 | */ |
1646 | fastcall unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order) | 1644 | unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order) |
1647 | { | 1645 | { |
1648 | struct page * page; | 1646 | struct page * page; |
1649 | page = alloc_pages(gfp_mask, order); | 1647 | page = alloc_pages(gfp_mask, order); |
@@ -1654,7 +1652,7 @@ fastcall unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order) | |||
1654 | 1652 | ||
1655 | EXPORT_SYMBOL(__get_free_pages); | 1653 | EXPORT_SYMBOL(__get_free_pages); |
1656 | 1654 | ||
1657 | fastcall unsigned long get_zeroed_page(gfp_t gfp_mask) | 1655 | unsigned long get_zeroed_page(gfp_t gfp_mask) |
1658 | { | 1656 | { |
1659 | struct page * page; | 1657 | struct page * page; |
1660 | 1658 | ||
@@ -1680,7 +1678,7 @@ void __pagevec_free(struct pagevec *pvec) | |||
1680 | free_hot_cold_page(pvec->pages[i], pvec->cold); | 1678 | free_hot_cold_page(pvec->pages[i], pvec->cold); |
1681 | } | 1679 | } |
1682 | 1680 | ||
1683 | fastcall void __free_pages(struct page *page, unsigned int order) | 1681 | void __free_pages(struct page *page, unsigned int order) |
1684 | { | 1682 | { |
1685 | if (put_page_testzero(page)) { | 1683 | if (put_page_testzero(page)) { |
1686 | if (order == 0) | 1684 | if (order == 0) |
@@ -1692,7 +1690,7 @@ fastcall void __free_pages(struct page *page, unsigned int order) | |||
1692 | 1690 | ||
1693 | EXPORT_SYMBOL(__free_pages); | 1691 | EXPORT_SYMBOL(__free_pages); |
1694 | 1692 | ||
1695 | fastcall void free_pages(unsigned long addr, unsigned int order) | 1693 | void free_pages(unsigned long addr, unsigned int order) |
1696 | { | 1694 | { |
1697 | if (addr != 0) { | 1695 | if (addr != 0) { |
1698 | VM_BUG_ON(!virt_addr_valid((void *)addr)); | 1696 | VM_BUG_ON(!virt_addr_valid((void *)addr)); |
@@ -1801,12 +1799,9 @@ void show_free_areas(void) | |||
1801 | 1799 | ||
1802 | pageset = zone_pcp(zone, cpu); | 1800 | pageset = zone_pcp(zone, cpu); |
1803 | 1801 | ||
1804 | printk("CPU %4d: Hot: hi:%5d, btch:%4d usd:%4d " | 1802 | printk("CPU %4d: hi:%5d, btch:%4d usd:%4d\n", |
1805 | "Cold: hi:%5d, btch:%4d usd:%4d\n", | 1803 | cpu, pageset->pcp.high, |
1806 | cpu, pageset->pcp[0].high, | 1804 | pageset->pcp.batch, pageset->pcp.count); |
1807 | pageset->pcp[0].batch, pageset->pcp[0].count, | ||
1808 | pageset->pcp[1].high, pageset->pcp[1].batch, | ||
1809 | pageset->pcp[1].count); | ||
1810 | } | 1805 | } |
1811 | } | 1806 | } |
1812 | 1807 | ||
@@ -1879,6 +1874,8 @@ void show_free_areas(void) | |||
1879 | printk("= %lukB\n", K(total)); | 1874 | printk("= %lukB\n", K(total)); |
1880 | } | 1875 | } |
1881 | 1876 | ||
1877 | printk("%ld total pagecache pages\n", global_page_state(NR_FILE_PAGES)); | ||
1878 | |||
1882 | show_swap_cache_info(); | 1879 | show_swap_cache_info(); |
1883 | } | 1880 | } |
1884 | 1881 | ||
@@ -2551,8 +2548,7 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone, | |||
2551 | } | 2548 | } |
2552 | } | 2549 | } |
2553 | 2550 | ||
2554 | static void __meminit zone_init_free_lists(struct pglist_data *pgdat, | 2551 | static void __meminit zone_init_free_lists(struct zone *zone) |
2555 | struct zone *zone, unsigned long size) | ||
2556 | { | 2552 | { |
2557 | int order, t; | 2553 | int order, t; |
2558 | for_each_migratetype_order(order, t) { | 2554 | for_each_migratetype_order(order, t) { |
@@ -2604,17 +2600,11 @@ inline void setup_pageset(struct per_cpu_pageset *p, unsigned long batch) | |||
2604 | 2600 | ||
2605 | memset(p, 0, sizeof(*p)); | 2601 | memset(p, 0, sizeof(*p)); |
2606 | 2602 | ||
2607 | pcp = &p->pcp[0]; /* hot */ | 2603 | pcp = &p->pcp; |
2608 | pcp->count = 0; | 2604 | pcp->count = 0; |
2609 | pcp->high = 6 * batch; | 2605 | pcp->high = 6 * batch; |
2610 | pcp->batch = max(1UL, 1 * batch); | 2606 | pcp->batch = max(1UL, 1 * batch); |
2611 | INIT_LIST_HEAD(&pcp->list); | 2607 | INIT_LIST_HEAD(&pcp->list); |
2612 | |||
2613 | pcp = &p->pcp[1]; /* cold*/ | ||
2614 | pcp->count = 0; | ||
2615 | pcp->high = 2 * batch; | ||
2616 | pcp->batch = max(1UL, batch/2); | ||
2617 | INIT_LIST_HEAD(&pcp->list); | ||
2618 | } | 2608 | } |
2619 | 2609 | ||
2620 | /* | 2610 | /* |
@@ -2627,7 +2617,7 @@ static void setup_pagelist_highmark(struct per_cpu_pageset *p, | |||
2627 | { | 2617 | { |
2628 | struct per_cpu_pages *pcp; | 2618 | struct per_cpu_pages *pcp; |
2629 | 2619 | ||
2630 | pcp = &p->pcp[0]; /* hot list */ | 2620 | pcp = &p->pcp; |
2631 | pcp->high = high; | 2621 | pcp->high = high; |
2632 | pcp->batch = max(1UL, high/4); | 2622 | pcp->batch = max(1UL, high/4); |
2633 | if ((high/4) > (PAGE_SHIFT * 8)) | 2623 | if ((high/4) > (PAGE_SHIFT * 8)) |
@@ -2831,7 +2821,7 @@ __meminit int init_currently_empty_zone(struct zone *zone, | |||
2831 | 2821 | ||
2832 | memmap_init(size, pgdat->node_id, zone_idx(zone), zone_start_pfn); | 2822 | memmap_init(size, pgdat->node_id, zone_idx(zone), zone_start_pfn); |
2833 | 2823 | ||
2834 | zone_init_free_lists(pgdat, zone, zone->spanned_pages); | 2824 | zone_init_free_lists(zone); |
2835 | 2825 | ||
2836 | return 0; | 2826 | return 0; |
2837 | } | 2827 | } |
@@ -3978,10 +3968,23 @@ static int page_alloc_cpu_notify(struct notifier_block *self, | |||
3978 | int cpu = (unsigned long)hcpu; | 3968 | int cpu = (unsigned long)hcpu; |
3979 | 3969 | ||
3980 | if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) { | 3970 | if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) { |
3981 | local_irq_disable(); | 3971 | drain_pages(cpu); |
3982 | __drain_pages(cpu); | 3972 | |
3973 | /* | ||
3974 | * Spill the event counters of the dead processor | ||
3975 | * into the current processors event counters. | ||
3976 | * This artificially elevates the count of the current | ||
3977 | * processor. | ||
3978 | */ | ||
3983 | vm_events_fold_cpu(cpu); | 3979 | vm_events_fold_cpu(cpu); |
3984 | local_irq_enable(); | 3980 | |
3981 | /* | ||
3982 | * Zero the differential counters of the dead processor | ||
3983 | * so that the vm statistics are consistent. | ||
3984 | * | ||
3985 | * This is only okay since the processor is dead and cannot | ||
3986 | * race with what we are doing. | ||
3987 | */ | ||
3985 | refresh_cpu_vm_stats(cpu); | 3988 | refresh_cpu_vm_stats(cpu); |
3986 | } | 3989 | } |
3987 | return NOTIFY_OK; | 3990 | return NOTIFY_OK; |
@@ -4480,7 +4483,7 @@ int set_migratetype_isolate(struct page *page) | |||
4480 | out: | 4483 | out: |
4481 | spin_unlock_irqrestore(&zone->lock, flags); | 4484 | spin_unlock_irqrestore(&zone->lock, flags); |
4482 | if (!ret) | 4485 | if (!ret) |
4483 | drain_all_local_pages(); | 4486 | drain_all_pages(); |
4484 | return ret; | 4487 | return ret; |
4485 | } | 4488 | } |
4486 | 4489 | ||