diff options
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r-- | mm/page_alloc.c | 50 |
1 files changed, 18 insertions, 32 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 6fd0b7455b0b..f9b5d6d5f4d6 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -691,43 +691,26 @@ static void __init setup_nr_node_ids(void) {} | |||
691 | 691 | ||
692 | #ifdef CONFIG_NUMA | 692 | #ifdef CONFIG_NUMA |
693 | /* | 693 | /* |
694 | * Called from the slab reaper to drain pagesets on a particular node that | 694 | * Called from the vmstat counter updater to drain pagesets of this |
695 | * belongs to the currently executing processor. | 695 | * currently executing processor on remote nodes after they have |
696 | * expired. | ||
697 | * | ||
696 | * Note that this function must be called with the thread pinned to | 698 | * Note that this function must be called with the thread pinned to |
697 | * a single processor. | 699 | * a single processor. |
698 | */ | 700 | */ |
699 | void drain_node_pages(int nodeid) | 701 | void drain_zone_pages(struct zone *zone, struct per_cpu_pages *pcp) |
700 | { | 702 | { |
701 | int i; | ||
702 | enum zone_type z; | ||
703 | unsigned long flags; | 703 | unsigned long flags; |
704 | int to_drain; | ||
704 | 705 | ||
705 | for (z = 0; z < MAX_NR_ZONES; z++) { | 706 | local_irq_save(flags); |
706 | struct zone *zone = NODE_DATA(nodeid)->node_zones + z; | 707 | if (pcp->count >= pcp->batch) |
707 | struct per_cpu_pageset *pset; | 708 | to_drain = pcp->batch; |
708 | 709 | else | |
709 | if (!populated_zone(zone)) | 710 | to_drain = pcp->count; |
710 | continue; | 711 | free_pages_bulk(zone, to_drain, &pcp->list, 0); |
711 | 712 | pcp->count -= to_drain; | |
712 | pset = zone_pcp(zone, smp_processor_id()); | 713 | local_irq_restore(flags); |
713 | for (i = 0; i < ARRAY_SIZE(pset->pcp); i++) { | ||
714 | struct per_cpu_pages *pcp; | ||
715 | |||
716 | pcp = &pset->pcp[i]; | ||
717 | if (pcp->count) { | ||
718 | int to_drain; | ||
719 | |||
720 | local_irq_save(flags); | ||
721 | if (pcp->count >= pcp->batch) | ||
722 | to_drain = pcp->batch; | ||
723 | else | ||
724 | to_drain = pcp->count; | ||
725 | free_pages_bulk(zone, to_drain, &pcp->list, 0); | ||
726 | pcp->count -= to_drain; | ||
727 | local_irq_restore(flags); | ||
728 | } | ||
729 | } | ||
730 | } | ||
731 | } | 714 | } |
732 | #endif | 715 | #endif |
733 | 716 | ||
@@ -2148,11 +2131,14 @@ static int __cpuinit pageset_cpuup_callback(struct notifier_block *nfb, | |||
2148 | 2131 | ||
2149 | switch (action) { | 2132 | switch (action) { |
2150 | case CPU_UP_PREPARE: | 2133 | case CPU_UP_PREPARE: |
2134 | case CPU_UP_PREPARE_FROZEN: | ||
2151 | if (process_zones(cpu)) | 2135 | if (process_zones(cpu)) |
2152 | ret = NOTIFY_BAD; | 2136 | ret = NOTIFY_BAD; |
2153 | break; | 2137 | break; |
2154 | case CPU_UP_CANCELED: | 2138 | case CPU_UP_CANCELED: |
2139 | case CPU_UP_CANCELED_FROZEN: | ||
2155 | case CPU_DEAD: | 2140 | case CPU_DEAD: |
2141 | case CPU_DEAD_FROZEN: | ||
2156 | free_zone_pagesets(cpu); | 2142 | free_zone_pagesets(cpu); |
2157 | break; | 2143 | break; |
2158 | default: | 2144 | default: |
@@ -3012,7 +2998,7 @@ static int page_alloc_cpu_notify(struct notifier_block *self, | |||
3012 | { | 2998 | { |
3013 | int cpu = (unsigned long)hcpu; | 2999 | int cpu = (unsigned long)hcpu; |
3014 | 3000 | ||
3015 | if (action == CPU_DEAD) { | 3001 | if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) { |
3016 | local_irq_disable(); | 3002 | local_irq_disable(); |
3017 | __drain_pages(cpu); | 3003 | __drain_pages(cpu); |
3018 | vm_events_fold_cpu(cpu); | 3004 | vm_events_fold_cpu(cpu); |