aboutsummaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-12-25 08:15:31 -0500
committerTakashi Iwai <tiwai@suse.de>2009-12-25 08:15:31 -0500
commit52e04ea89da57274f0313d2bd73ba02f686cfdeb (patch)
tree6ce5d086bcaea4cb534b3fcf6ba736eb48d582a4 /mm/page_alloc.c
parent41116e926cb92292fa4fcbe888ae8133fa0038e6 (diff)
parent8b90ca08821fee79e181bfcbc3bbd41ef5637136 (diff)
Merge branch 'fix/misc' into topic/misc
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r--mm/page_alloc.c72
1 files changed, 59 insertions, 13 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 74af449b1f1d..4e9f5cc5fb59 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -48,6 +48,7 @@
48#include <linux/page_cgroup.h> 48#include <linux/page_cgroup.h>
49#include <linux/debugobjects.h> 49#include <linux/debugobjects.h>
50#include <linux/kmemleak.h> 50#include <linux/kmemleak.h>
51#include <linux/memory.h>
51#include <trace/events/kmem.h> 52#include <trace/events/kmem.h>
52 53
53#include <asm/tlbflush.h> 54#include <asm/tlbflush.h>
@@ -2401,13 +2402,14 @@ int numa_zonelist_order_handler(ctl_table *table, int write,
2401{ 2402{
2402 char saved_string[NUMA_ZONELIST_ORDER_LEN]; 2403 char saved_string[NUMA_ZONELIST_ORDER_LEN];
2403 int ret; 2404 int ret;
2405 static DEFINE_MUTEX(zl_order_mutex);
2404 2406
2407 mutex_lock(&zl_order_mutex);
2405 if (write) 2408 if (write)
2406 strncpy(saved_string, (char*)table->data, 2409 strcpy(saved_string, (char*)table->data);
2407 NUMA_ZONELIST_ORDER_LEN);
2408 ret = proc_dostring(table, write, buffer, length, ppos); 2410 ret = proc_dostring(table, write, buffer, length, ppos);
2409 if (ret) 2411 if (ret)
2410 return ret; 2412 goto out;
2411 if (write) { 2413 if (write) {
2412 int oldval = user_zonelist_order; 2414 int oldval = user_zonelist_order;
2413 if (__parse_numa_zonelist_order((char*)table->data)) { 2415 if (__parse_numa_zonelist_order((char*)table->data)) {
@@ -2420,7 +2422,9 @@ int numa_zonelist_order_handler(ctl_table *table, int write,
2420 } else if (oldval != user_zonelist_order) 2422 } else if (oldval != user_zonelist_order)
2421 build_all_zonelists(); 2423 build_all_zonelists();
2422 } 2424 }
2423 return 0; 2425out:
2426 mutex_unlock(&zl_order_mutex);
2427 return ret;
2424} 2428}
2425 2429
2426 2430
@@ -3579,7 +3583,7 @@ static unsigned long __meminit zone_spanned_pages_in_node(int nid,
3579 * Return the number of holes in a range on a node. If nid is MAX_NUMNODES, 3583 * Return the number of holes in a range on a node. If nid is MAX_NUMNODES,
3580 * then all holes in the requested range will be accounted for. 3584 * then all holes in the requested range will be accounted for.
3581 */ 3585 */
3582static unsigned long __meminit __absent_pages_in_range(int nid, 3586unsigned long __meminit __absent_pages_in_range(int nid,
3583 unsigned long range_start_pfn, 3587 unsigned long range_start_pfn,
3584 unsigned long range_end_pfn) 3588 unsigned long range_end_pfn)
3585{ 3589{
@@ -4108,7 +4112,7 @@ static int __init cmp_node_active_region(const void *a, const void *b)
4108} 4112}
4109 4113
4110/* sort the node_map by start_pfn */ 4114/* sort the node_map by start_pfn */
4111static void __init sort_node_map(void) 4115void __init sort_node_map(void)
4112{ 4116{
4113 sort(early_node_map, (size_t)nr_nodemap_entries, 4117 sort(early_node_map, (size_t)nr_nodemap_entries,
4114 sizeof(struct node_active_region), 4118 sizeof(struct node_active_region),
@@ -5008,23 +5012,65 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags,
5008int set_migratetype_isolate(struct page *page) 5012int set_migratetype_isolate(struct page *page)
5009{ 5013{
5010 struct zone *zone; 5014 struct zone *zone;
5011 unsigned long flags; 5015 struct page *curr_page;
5016 unsigned long flags, pfn, iter;
5017 unsigned long immobile = 0;
5018 struct memory_isolate_notify arg;
5019 int notifier_ret;
5012 int ret = -EBUSY; 5020 int ret = -EBUSY;
5013 int zone_idx; 5021 int zone_idx;
5014 5022
5015 zone = page_zone(page); 5023 zone = page_zone(page);
5016 zone_idx = zone_idx(zone); 5024 zone_idx = zone_idx(zone);
5025
5017 spin_lock_irqsave(&zone->lock, flags); 5026 spin_lock_irqsave(&zone->lock, flags);
5027 if (get_pageblock_migratetype(page) == MIGRATE_MOVABLE ||
5028 zone_idx == ZONE_MOVABLE) {
5029 ret = 0;
5030 goto out;
5031 }
5032
5033 pfn = page_to_pfn(page);
5034 arg.start_pfn = pfn;
5035 arg.nr_pages = pageblock_nr_pages;
5036 arg.pages_found = 0;
5037
5018 /* 5038 /*
5019 * In future, more migrate types will be able to be isolation target. 5039 * It may be possible to isolate a pageblock even if the
5040 * migratetype is not MIGRATE_MOVABLE. The memory isolation
5041 * notifier chain is used by balloon drivers to return the
5042 * number of pages in a range that are held by the balloon
5043 * driver to shrink memory. If all the pages are accounted for
5044 * by balloons, are free, or on the LRU, isolation can continue.
5045 * Later, for example, when memory hotplug notifier runs, these
5046 * pages reported as "can be isolated" should be isolated(freed)
5047 * by the balloon driver through the memory notifier chain.
5020 */ 5048 */
5021 if (get_pageblock_migratetype(page) != MIGRATE_MOVABLE && 5049 notifier_ret = memory_isolate_notify(MEM_ISOLATE_COUNT, &arg);
5022 zone_idx != ZONE_MOVABLE) 5050 notifier_ret = notifier_to_errno(notifier_ret);
5051 if (notifier_ret || !arg.pages_found)
5023 goto out; 5052 goto out;
5024 set_pageblock_migratetype(page, MIGRATE_ISOLATE); 5053
5025 move_freepages_block(zone, page, MIGRATE_ISOLATE); 5054 for (iter = pfn; iter < (pfn + pageblock_nr_pages); iter++) {
5026 ret = 0; 5055 if (!pfn_valid_within(pfn))
5056 continue;
5057
5058 curr_page = pfn_to_page(iter);
5059 if (!page_count(curr_page) || PageLRU(curr_page))
5060 continue;
5061
5062 immobile++;
5063 }
5064
5065 if (arg.pages_found == immobile)
5066 ret = 0;
5067
5027out: 5068out:
5069 if (!ret) {
5070 set_pageblock_migratetype(page, MIGRATE_ISOLATE);
5071 move_freepages_block(zone, page, MIGRATE_ISOLATE);
5072 }
5073
5028 spin_unlock_irqrestore(&zone->lock, flags); 5074 spin_unlock_irqrestore(&zone->lock, flags);
5029 if (!ret) 5075 if (!ret)
5030 drain_all_pages(); 5076 drain_all_pages();